Merge llvm-project main llvmorg-15-init-17485-ga3e38b4a206b

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-15-init-17485-ga3e38b4a206b.

PR:		265425
MFC after:	2 weeks
This commit is contained in:
Dimitry Andric 2022-07-24 17:11:41 +02:00
commit fcaf7f8644
989 changed files with 24086 additions and 10468 deletions

View File

@ -77,7 +77,7 @@ class CommonEntityInfo {
void setSwiftPrivate(llvm::Optional<bool> Private) {
SwiftPrivateSpecified = Private.has_value();
SwiftPrivate = Private ? *Private : 0;
SwiftPrivate = Private.value_or(0);
}
friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &);

View File

@ -473,6 +473,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
};
llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;
/// For module code-gen cases, this is the top-level module we are building.
Module *TopLevelModule = nullptr;
static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
static constexpr unsigned GeneralTypesLog2InitSize = 9;
static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
@ -1076,6 +1079,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Get the initializations to perform when importing a module, if any.
ArrayRef<Decl*> getModuleInitializers(Module *M);
/// Set the (C++20) module we are building.
void setModuleForCodeGen(Module *M) { TopLevelModule = M; }
/// Get module under construction, nullptr if this is not a C++20 module.
Module *getModuleForCodeGen() const { return TopLevelModule; }
TranslationUnitDecl *getTranslationUnitDecl() const {
return TUDecl->getMostRecentDecl();
}

View File

@ -1887,7 +1887,10 @@ class FunctionDecl : public DeclaratorDecl,
TK_FunctionTemplateSpecialization,
// A function template specialization that hasn't yet been resolved to a
// particular specialized function template.
TK_DependentFunctionTemplateSpecialization
TK_DependentFunctionTemplateSpecialization,
// A non-template function which is in a dependent scope.
TK_DependentNonTemplate
};
/// Stashed information about a defaulted function definition whose body has
@ -1936,20 +1939,21 @@ class FunctionDecl : public DeclaratorDecl,
/// The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// For non-templates, this value will be NULL. For function
/// declarations that describe a function template, this will be a
/// pointer to a FunctionTemplateDecl. For member functions
/// of class template specializations, this will be a MemberSpecializationInfo
/// For non-templates this value will be NULL, unless this declaration was
/// declared directly inside of a function template, in which case it will
/// have a pointer to a FunctionDecl, stored in the NamedDecl. For function
/// declarations that describe a function template, this will be a pointer to
/// a FunctionTemplateDecl, stored in the NamedDecl. For member functions of
/// class template specializations, this will be a MemberSpecializationInfo
/// pointer containing information about the specialization.
/// For function template specializations, this will be a
/// FunctionTemplateSpecializationInfo, which contains information about
/// the template being specialized and the template arguments involved in
/// that specialization.
llvm::PointerUnion<FunctionTemplateDecl *,
MemberSpecializationInfo *,
llvm::PointerUnion<NamedDecl *, MemberSpecializationInfo *,
FunctionTemplateSpecializationInfo *,
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
TemplateOrSpecialization;
/// Provides source/type location info for the declaration name embedded in
/// the DeclaratorDecl base class.
@ -2692,6 +2696,13 @@ class FunctionDecl : public DeclaratorDecl,
setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
}
/// Specify that this function declaration was instantiated from a
/// FunctionDecl FD. This is only used if this is a function declaration
/// declared locally inside of a function template.
void setInstantiatedFromDecl(FunctionDecl *FD);
FunctionDecl *getInstantiatedFromDecl() const;
/// Retrieves the function template that is described by this
/// function declaration.
///

View File

@ -920,10 +920,12 @@ class alignas(8) Decl {
/// If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
DeclContext *getParentFunctionOrMethod() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
const DeclContext *
getParentFunctionOrMethod(bool LexicalParent = false) const;
DeclContext *getParentFunctionOrMethod(bool LexicalParent = false) {
return const_cast<DeclContext *>(
const_cast<const Decl *>(this)->getParentFunctionOrMethod(
LexicalParent));
}
/// Retrieves the "canonical" declaration of the given declaration.

View File

@ -3838,8 +3838,9 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
/// Matches if the call expression's callee's declaration matches the
/// given matcher.
/// Matches 1) if the call expression's callee's declaration matches the
/// given matcher; or 2) if the Obj-C message expression's callee's method
/// declaration matches the given matcher.
///
/// Example matches y.x() (matcher = callExpr(callee(
/// cxxMethodDecl(hasName("x")))))
@ -3847,9 +3848,31 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
/// class Y { public: void x(); };
/// void z() { Y y; y.x(); }
/// \endcode
AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
1) {
return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder);
///
/// Example 2. Matches [I foo] with
/// objcMessageExpr(callee(objcMethodDecl(hasName("foo"))))
///
/// \code
/// @interface I: NSObject
/// +(void)foo;
/// @end
/// ...
/// [I foo]
/// \endcode
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
callee, AST_POLYMORPHIC_SUPPORTED_TYPES(ObjCMessageExpr, CallExpr),
internal::Matcher<Decl>, InnerMatcher, 1) {
if (const auto *CallNode = dyn_cast<CallExpr>(&Node))
return callExpr(hasDeclaration(InnerMatcher))
.matches(Node, Finder, Builder);
else {
// The dynamic cast below is guaranteed to succeed as there are only 2
// supported return types.
const auto *MsgNode = cast<ObjCMessageExpr>(&Node);
const Decl *DeclNode = MsgNode->getMethodDecl();
return (DeclNode != nullptr &&
InnerMatcher.matches(*DeclNode, Finder, Builder));
}
}
/// Matches if the expression's or declaration's type matches a type

View File

@ -75,7 +75,7 @@ namespace til {
class BasicBlock;
/// Enum for the different distinct classes of SExpr
enum TIL_Opcode {
enum TIL_Opcode : unsigned char {
#define TIL_OPCODE_DEF(X) COP_##X,
#include "ThreadSafetyOps.def"
#undef TIL_OPCODE_DEF
@ -278,7 +278,7 @@ class SExpr {
public:
SExpr() = delete;
TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
TIL_Opcode opcode() const { return Opcode; }
// Subclasses of SExpr must define the following:
//
@ -321,7 +321,7 @@ class SExpr {
SExpr(TIL_Opcode Op) : Opcode(Op) {}
SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {}
const unsigned char Opcode;
const TIL_Opcode Opcode;
unsigned char Reserved = 0;
unsigned short Flags = 0;
unsigned SExprID = 0;
@ -332,7 +332,7 @@ class SExpr {
namespace ThreadSafetyTIL {
inline bool isTrivial(const SExpr *E) {
unsigned Op = E->opcode();
TIL_Opcode Op = E->opcode();
return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
}

View File

@ -63,9 +63,15 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
using Lattice = LatticeT;
explicit DataflowAnalysis(ASTContext &Context) : Context(Context) {}
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
explicit DataflowAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
: TypeErasedDataflowAnalysis(ApplyBuiltinTransfer), Context(Context) {}
explicit DataflowAnalysis(ASTContext &Context,
DataflowAnalysisOptions Options)
: TypeErasedDataflowAnalysis(Options), Context(Context) {}
ASTContext &getASTContext() final { return Context; }
TypeErasedLattice typeErasedInitialElement() final {

View File

@ -23,6 +23,7 @@
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <memory>
#include <type_traits>
@ -251,6 +252,8 @@ class DataflowAnalysisContext {
/// `Val2` imposed by the flow condition.
bool equivalentBoolValues(BoolValue &Val1, BoolValue &Val2);
LLVM_DUMP_METHOD void dumpFlowCondition(AtomicBoolValue &Token);
private:
struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> {
static QualType getEmptyKey() {

View File

@ -19,7 +19,6 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
@ -325,6 +324,8 @@ class Environment {
/// imply that `Val` is true.
bool flowConditionImplies(BoolValue &Val) const;
LLVM_DUMP_METHOD void dump() const;
private:
/// Creates a value appropriate for `Type`, if `Type` is supported, otherwise
/// return null.

View File

@ -23,6 +23,13 @@
namespace clang {
namespace dataflow {
/// Returns a string representation of a boolean assignment to true or false.
std::string debugString(Solver::Result::Assignment Assignment);
/// Returns a string representation of the result status of a SAT check.
std::string debugString(Solver::Result::Status Status);
/// Returns a string representation for the boolean value `B`.
///
/// Atomic booleans appearing in the boolean value `B` are assigned to labels
@ -35,6 +42,20 @@ std::string debugString(
const BoolValue &B,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
/// Returns a string representation for `Constraints` - a collection of boolean
/// formulas.
///
/// Atomic booleans appearing in the boolean value `Constraints` are assigned to
/// labels either specified in `AtomNames` or created by default rules as B0,
/// B1, ...
///
/// Requirements:
///
/// Names assigned to atoms should not be repeated in `AtomNames`.
std::string debugString(
const llvm::DenseSet<BoolValue *> &Constraints,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
/// Returns a string representation for `Constraints` - a collection of boolean
/// formulas and the `Result` of satisfiability checking.
///
@ -46,7 +67,7 @@ std::string debugString(
///
/// Names assigned to atoms should not be repeated in `AtomNames`.
std::string debugString(
const std::vector<BoolValue *> &Constraints, const Solver::Result &Result,
ArrayRef<BoolValue *> Constraints, const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {{}});
inline std::string debugString(
const llvm::DenseSet<BoolValue *> &Constraints,

View File

@ -0,0 +1,47 @@
//===-- NoopAnalysis.h ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines a NoopAnalysis class that just uses the builtin transfer.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
namespace clang {
namespace dataflow {
class NoopAnalysis : public DataflowAnalysis<NoopAnalysis, NoopLattice> {
public:
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
NoopAnalysis(ASTContext &Context, bool ApplyBuiltinTransfer)
: DataflowAnalysis<NoopAnalysis, NoopLattice>(Context,
ApplyBuiltinTransfer) {}
/// `ApplyBuiltinTransfer` controls whether to run the built-in transfer
/// functions that model memory during the analysis. Their results are not
/// used by `NoopAnalysis`, but tests that need to inspect the environment
/// should enable them.
NoopAnalysis(ASTContext &Context, DataflowAnalysisOptions Options)
: DataflowAnalysis<NoopAnalysis, NoopLattice>(Context, Options) {}
static NoopLattice initialElement() { return {}; }
void transfer(const Stmt *S, NoopLattice &E, Environment &Env) {}
};
} // namespace dataflow
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_NOOPANALYSIS_H

View File

@ -30,6 +30,14 @@
namespace clang {
namespace dataflow {
struct DataflowAnalysisOptions {
/// Determines whether to apply the built-in transfer functions.
// FIXME: Remove this option once the framework supports composing analyses
// (at which point the built-in transfer functions can be simply a standalone
// analysis).
bool ApplyBuiltinTransfer = true;
};
/// Type-erased lattice element container.
///
/// Requirements:
@ -42,16 +50,17 @@ struct TypeErasedLattice {
/// Type-erased base class for dataflow analyses built on a single lattice type.
class TypeErasedDataflowAnalysis : public Environment::ValueModel {
/// Determines whether to apply the built-in transfer functions.
// FIXME: Remove this option once the framework supports composing analyses
// (at which point the built-in transfer functions can be simply a standalone
// analysis).
bool ApplyBuiltinTransfer;
DataflowAnalysisOptions Options;
public:
TypeErasedDataflowAnalysis() : ApplyBuiltinTransfer(true) {}
TypeErasedDataflowAnalysis() : Options({}) {}
/// Deprecated. Use the `DataflowAnalysisOptions` constructor instead.
TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer)
: ApplyBuiltinTransfer(ApplyBuiltinTransfer) {}
: Options({ApplyBuiltinTransfer}) {}
TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options)
: Options(Options) {}
virtual ~TypeErasedDataflowAnalysis() {}
@ -80,7 +89,7 @@ class TypeErasedDataflowAnalysis : public Environment::ValueModel {
/// Determines whether to apply the built-in transfer functions, which model
/// the heap and stack in the `Environment`.
bool applyBuiltinTransfer() const { return ApplyBuiltinTransfer; }
bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; }
};
/// Type-erased model of the program at a given program point.

View File

@ -2703,7 +2703,7 @@ def Target : InheritableAttr {
template<class Compare>
ParsedTargetAttr parse(Compare cmp) const {
ParsedTargetAttr Attrs = parse();
llvm::sort(std::begin(Attrs.Features), std::end(Attrs.Features), cmp);
llvm::sort(Attrs.Features, cmp);
return Attrs;
}

View File

@ -339,12 +339,37 @@ TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_16x16x32_i8, "V4iWiWiV4iIiIiIi", "nc",
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_32x32x16_i8, "V16iWiWiV16iIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x8_xf32, "V4fV2fV2fV4fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x4_xf32, "V16fV2fV2fV16fIiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_bf8_bf8, "V4fWiWiV4fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_bf8_fp8, "V4fWiWiV4fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_fp8_bf8, "V4fWiWiV4fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_fp8_fp8, "V4fWiWiV4fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_bf8_bf8, "V16fWiWiV16fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_bf8_fp8, "V16fWiWiV16fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_fp8_bf8, "V16fWiWiV16fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_fp8_fp8, "V16fWiWiV16fIiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x32_f16, "V4fV4hV8hV4fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x16_f16, "V16fV4hV8hV16fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x32_bf16, "V4fV4sV8sV4fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x16_bf16, "V16fV4sV8sV16fiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_16x16x64_i8, "V4iV2iV4iV4iiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_32x32x32_i8, "V16iV2iV4iV16iiIiIi", "nc", "mai-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_bf8_bf8, "V4fV2iV4iV4fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_bf8_fp8, "V4fV2iV4iV4fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_fp8_bf8, "V4fV2iV4iV4fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_fp8_fp8, "V4fV2iV4iV4fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_bf8_bf8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_bf8_fp8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_fp8_bf8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_fp8_fp8, "V16fV2iV4iV16fiIiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_bf8, "fiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_f32_fp8, "fiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_bf8, "V2fiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f32_fp8, "V2fiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_bf8_f32, "iffiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-insts")
#undef BUILTIN
#undef TARGET_BUILTIN

View File

@ -213,6 +213,10 @@ CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic
ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone)
/// Choose profile kind for PGO use compilation.
ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone)
/// Partition functions into N groups and select only functions in group i to be
/// instrumented. Selected group numbers can be 0 to N-1 inclusive.
VALUE_CODEGENOPT(ProfileTotalFunctionGroups, 32, 1)
VALUE_CODEGENOPT(ProfileSelectedFunctionGroup, 32, 0)
CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
///< enable code coverage analysis.
CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping

View File

@ -678,4 +678,11 @@ def err_drv_invalid_format_dxil_validator_version : Error<
def err_drv_invalid_empty_dxil_validator_version : Error<
"invalid validator version : %0\n"
"If validator major version is 0, minor version must also be 0.">;
def warn_drv_sarif_format_unstable : Warning<
"diagnostic formatting in SARIF mode is currently unstable">,
InGroup<DiagGroup<"sarif-format-unstable">>;
def err_drv_riscv_unsupported_with_linker_relaxation : Error<
"%0 is unsupported with RISC-V linker relaxation (-mrelax)">;
}

View File

@ -35,7 +35,7 @@ def ArrayParameter : DiagGroup<"array-parameter">;
def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">;
def Availability : DiagGroup<"availability">;
def Section : DiagGroup<"section">;
def AutoImport : DiagGroup<"auto-import">;
def : DiagGroup<"auto-import">;
def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">;
def FrameworkIncludePrivateFromPublic :
DiagGroup<"framework-include-private-from-public">;
@ -490,6 +490,7 @@ def ModuleBuild : DiagGroup<"module-build">;
def ModuleImport : DiagGroup<"module-import">;
def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;

View File

@ -387,7 +387,15 @@ def ext_pp_include_search_ms : ExtWarn<
def ext_pp_ident_directive : Extension<"#ident is a language extension">;
def ext_pp_include_next_directive : Extension<
"#include_next is a language extension">, InGroup<GNUIncludeNext>;
def ext_pp_warning_directive : Extension<"#warning is a language extension">;
def ext_pp_warning_directive : Extension<
"#warning is a %select{C2x|C++2b}0 extension">;
def warn_cxx2b_compat_warning_directive : Warning<
"#warning is incompatible with C++ standards before C++2b">,
InGroup<CXXPre2bCompat>, DefaultIgnore;
def warn_c2x_compat_warning_directive : Warning<
"#warning is incompatible with C standards before C2x">,
InGroup<CPre2xCompat>, DefaultIgnore;
def ext_pp_extra_tokens_at_eol : ExtWarn<
"extra tokens at end of #%0 directive">, InGroup<ExtraTokens>;
@ -851,9 +859,9 @@ def warn_framework_include_private_from_public : Warning<
"public framework header includes private framework header '%0'"
>, InGroup<FrameworkIncludePrivateFromPublic>;
def warn_auto_module_import : Warning<
def remark_pp_include_directive_modular_translation : Remark<
"treating #%select{include|import|include_next|__include_macros}0 as an "
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
"import of module '%1'">, InGroup<ModuleIncludeDirectiveTranslation>;
def note_implicit_top_level_module_import_here : Note<
"submodule of top-level module '%0' implicitly imported here">;
def warn_uncovered_module_header : Warning<

View File

@ -74,7 +74,7 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
friend class CompilerInvocation;
public:
enum TextDiagnosticFormat { Clang, MSVC, Vi };
enum TextDiagnosticFormat { Clang, MSVC, Vi, SARIF };
// Default values.
enum {

View File

@ -8037,24 +8037,6 @@ def err_incompatible_qualified_id : Error<
"sending type to parameter of incompatible type}0,1"
"|%diff{casting $ to incompatible type $|"
"casting type to incompatible type}0,1}2">;
def ext_typecheck_convert_pointer_int : ExtWarn<
"incompatible pointer to integer conversion "
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
"|%diff{passing $ to parameter of type $|"
"passing to parameter of different type}0,1"
"|%diff{returning $ from a function with result type $|"
"returning from function with different return type}0,1"
"|%diff{converting $ to type $|converting between types}0,1"
"|%diff{initializing $ with an expression of type $|"
"initializing with expression of different type}0,1"
"|%diff{sending $ to parameter of type $|"
"sending to parameter of different type}0,1"
"|%diff{casting $ to type $|casting between types}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
"; remove &}3">,
InGroup<IntConversion>;
def err_typecheck_convert_pointer_int : Error<
"incompatible pointer to integer conversion "
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
@ -8072,24 +8054,9 @@ def err_typecheck_convert_pointer_int : Error<
"; take the address with &|"
"; remove *|"
"; remove &}3">;
def ext_typecheck_convert_int_pointer : ExtWarn<
"incompatible integer to pointer conversion "
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
"|%diff{passing $ to parameter of type $|"
"passing to parameter of different type}0,1"
"|%diff{returning $ from a function with result type $|"
"returning from function with different return type}0,1"
"|%diff{converting $ to type $|converting between types}0,1"
"|%diff{initializing $ with an expression of type $|"
"initializing with expression of different type}0,1"
"|%diff{sending $ to parameter of type $|"
"sending to parameter of different type}0,1"
"|%diff{casting $ to type $|casting between types}0,1}2"
"%select{|; dereference with *|"
"; take the address with &|"
"; remove *|"
"; remove &}3">,
InGroup<IntConversion>, SFINAEFailure;
def ext_typecheck_convert_pointer_int : ExtWarn<
err_typecheck_convert_pointer_int.Text>,
InGroup<IntConversion>, DefaultError;
def err_typecheck_convert_int_pointer : Error<
"incompatible integer to pointer conversion "
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
@ -8107,6 +8074,9 @@ def err_typecheck_convert_int_pointer : Error<
"; take the address with &|"
"; remove *|"
"; remove &}3">;
def ext_typecheck_convert_int_pointer : ExtWarn<
err_typecheck_convert_int_pointer.Text>,
InGroup<IntConversion>, DefaultError;
def ext_typecheck_convert_pointer_void_func : Extension<
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
"|%diff{passing $ to parameter of type $|"

View File

@ -179,7 +179,6 @@ FEATURE(cxx_thread_local,
FEATURE(cxx_trailing_return, LangOpts.CPlusPlus11)
FEATURE(cxx_unicode_literals, LangOpts.CPlusPlus11)
FEATURE(cxx_unrestricted_unions, LangOpts.CPlusPlus11)
FEATURE(cxx_unstable, LangOpts.Unstable)
FEATURE(cxx_user_literals, LangOpts.CPlusPlus11)
FEATURE(cxx_variadic_templates, LangOpts.CPlusPlus11)
// C++14 features
@ -235,6 +234,7 @@ FEATURE(shadow_call_stack,
LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
FEATURE(tls, PP.getTargetInfo().isTLSSupported())
FEATURE(underlying_type, LangOpts.CPlusPlus)
FEATURE(experimental_library, LangOpts.ExperimentalLibrary)
// C11 features supported by other languages as extensions.
EXTENSION(c_alignas, true)

View File

@ -155,7 +155,7 @@ LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
LANGOPT(Coroutines , 1, 0, "C++20 coroutines")
LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods")
LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
LANGOPT(Unstable , 1, 0, "Enable unstable and experimental features")
LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features")
LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
@ -424,6 +424,7 @@ LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors")
LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type")
LANGOPT(StrictFlexArrays, 2, 0, "Rely on strict definition of flexible arrays")
COMPATIBLE_VALUE_LANGOPT(MaxTokens, 32, 0, "Max number of tokens per TU or 0")

View File

@ -665,6 +665,18 @@ class Module {
Module *findSubmodule(StringRef Name) const;
Module *findOrInferSubmodule(StringRef Name);
/// Get the Global Module Fragment (sub-module) for this module, it there is
/// one.
///
/// \returns The GMF sub-module if found, or NULL otherwise.
Module *getGlobalModuleFragment() { return findSubmodule("<global>"); }
/// Get the Private Module Fragment (sub-module) for this module, it there is
/// one.
///
/// \returns The PMF sub-module if found, or NULL otherwise.
Module *getPrivateModuleFragment() { return findSubmodule("<private>"); }
/// Determine whether the specified module would be visible to
/// a lookup at the end of this module.
///

View File

@ -41,6 +41,8 @@ class NoSanitizeList {
bool containsFunction(SanitizerMask Mask, StringRef FunctionName) const;
bool containsFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
bool containsMainFile(SanitizerMask Mask, StringRef FileName,
StringRef Category = StringRef()) const;
bool containsLocation(SanitizerMask Mask, SourceLocation Loc,
StringRef Category = StringRef()) const;
};

View File

@ -0,0 +1,440 @@
//== clang/Basic/Sarif.h - SARIF Diagnostics Object Model -------*- C++ -*--==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
/// Defines clang::SarifDocumentWriter, clang::SarifRule, clang::SarifResult.
///
/// The document built can be accessed as a JSON Object.
/// Several value semantic types are also introduced which represent properties
/// of the SARIF standard, such as 'artifact', 'result', 'rule'.
///
/// A SARIF (Static Analysis Results Interchange Format) document is JSON
/// document that describes in detail the results of running static analysis
/// tools on a project. Each (non-trivial) document consists of at least one
/// "run", which are themselves composed of details such as:
/// * Tool: The tool that was run
/// * Rules: The rules applied during the tool run, represented by
/// \c reportingDescriptor objects in SARIF
/// * Results: The matches for the rules applied against the project(s) being
/// evaluated, represented by \c result objects in SARIF
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html">The SARIF standard</a>
/// 2. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317836">SARIF<pre>reportingDescriptor</pre></a>
/// 3. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317638">SARIF<pre>result</pre></a>
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_SARIF_H
#define LLVM_CLANG_BASIC_SARIF_H
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Version.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <string>
namespace clang {
class SarifDocumentWriter;
class SourceManager;
namespace detail {
/// \internal
/// An artifact location is SARIF's way of describing the complete location
/// of an artifact encountered during analysis. The \c artifactLocation object
/// typically consists of a URI, and/or an index to reference the artifact it
/// locates.
///
/// This builder makes an additional assumption: that every artifact encountered
/// by \c clang will be a physical, top-level artifact. Which is why the static
/// creation method \ref SarifArtifactLocation::create takes a mandatory URI
/// parameter. The official standard states that either a \c URI or \c Index
/// must be available in the object, \c clang picks the \c URI as a reasonable
/// default, because it intends to deal in physical artifacts for now.
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317427">artifactLocation object</a>
/// 2. \ref SarifArtifact
class SarifArtifactLocation {
private:
friend class clang::SarifDocumentWriter;
llvm::Optional<uint32_t> Index;
std::string URI;
SarifArtifactLocation() = delete;
explicit SarifArtifactLocation(const std::string &URI) : URI(URI) {}
public:
static SarifArtifactLocation create(llvm::StringRef URI) {
return SarifArtifactLocation{URI.str()};
}
SarifArtifactLocation setIndex(uint32_t Idx) {
Index = Idx;
return *this;
}
};
/// \internal
/// An artifact in SARIF is any object (a sequence of bytes) addressable by
/// a URI (RFC 3986). The most common type of artifact for clang's use-case
/// would be source files. SARIF's artifact object is described in detail in
/// section 3.24.
//
/// Since every clang artifact MUST have a location (there being no nested
/// artifacts), the creation method \ref SarifArtifact::create requires a
/// \ref SarifArtifactLocation object.
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317611">artifact object</a>
class SarifArtifact {
private:
friend class clang::SarifDocumentWriter;
llvm::Optional<uint32_t> Offset;
llvm::Optional<size_t> Length;
std::string MimeType;
SarifArtifactLocation Location;
llvm::SmallVector<std::string, 4> Roles;
SarifArtifact() = delete;
explicit SarifArtifact(const SarifArtifactLocation &Loc) : Location(Loc) {}
public:
static SarifArtifact create(const SarifArtifactLocation &Loc) {
return SarifArtifact{Loc};
}
SarifArtifact setOffset(uint32_t ArtifactOffset) {
Offset = ArtifactOffset;
return *this;
}
SarifArtifact setLength(size_t NumBytes) {
Length = NumBytes;
return *this;
}
SarifArtifact setRoles(std::initializer_list<llvm::StringRef> ArtifactRoles) {
Roles.assign(ArtifactRoles.begin(), ArtifactRoles.end());
return *this;
}
SarifArtifact setMimeType(llvm::StringRef ArtifactMimeType) {
MimeType = ArtifactMimeType.str();
return *this;
}
};
} // namespace detail
enum class ThreadFlowImportance { Important, Essential, Unimportant };
/// A thread flow is a sequence of code locations that specify a possible path
/// through a single thread of execution.
/// A thread flow in SARIF is related to a code flow which describes
/// the progress of one or more programs through one or more thread flows.
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317744">threadFlow object</a>
/// 2. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317740">codeFlow object</a>
class ThreadFlow {
friend class SarifDocumentWriter;
CharSourceRange Range;
ThreadFlowImportance Importance;
std::string Message;
ThreadFlow() = default;
public:
static ThreadFlow create() { return {}; }
ThreadFlow setRange(const CharSourceRange &ItemRange) {
assert(ItemRange.isCharRange() &&
"ThreadFlows require a character granular source range!");
Range = ItemRange;
return *this;
}
ThreadFlow setImportance(const ThreadFlowImportance &ItemImportance) {
Importance = ItemImportance;
return *this;
}
ThreadFlow setMessage(llvm::StringRef ItemMessage) {
Message = ItemMessage.str();
return *this;
}
};
/// A SARIF rule (\c reportingDescriptor object) contains information that
/// describes a reporting item generated by a tool. A reporting item is
/// either a result of analysis or notification of a condition encountered by
/// the tool. Rules are arbitrary but are identifiable by a hierarchical
/// rule-id.
///
/// This builder provides an interface to create SARIF \c reportingDescriptor
/// objects via the \ref SarifRule::create static method.
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317836">reportingDescriptor object</a>
class SarifRule {
friend class clang::SarifDocumentWriter;
std::string Name;
std::string Id;
std::string Description;
std::string HelpURI;
SarifRule() = default;
public:
static SarifRule create() { return {}; }
SarifRule setName(llvm::StringRef RuleName) {
Name = RuleName.str();
return *this;
}
SarifRule setRuleId(llvm::StringRef RuleId) {
Id = RuleId.str();
return *this;
}
SarifRule setDescription(llvm::StringRef RuleDesc) {
Description = RuleDesc.str();
return *this;
}
SarifRule setHelpURI(llvm::StringRef RuleHelpURI) {
HelpURI = RuleHelpURI.str();
return *this;
}
};
/// A SARIF result (also called a "reporting item") is a unit of output
/// produced when one of the tool's \c reportingDescriptor encounters a match
/// on the file being analysed by the tool.
///
/// This builder provides a \ref SarifResult::create static method that can be
/// used to create an empty shell onto which attributes can be added using the
/// \c setX(...) methods.
///
/// For example:
/// \code{.cpp}
/// SarifResult result = SarifResult::create(...)
/// .setRuleId(...)
/// .setDiagnosticMessage(...);
/// \endcode
///
/// Reference:
/// 1. <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317638">SARIF<pre>result</pre></a>
class SarifResult {
friend class clang::SarifDocumentWriter;
// NOTE:
// This type cannot fit all possible indexes representable by JSON, but is
// chosen because it is the largest unsigned type that can be safely
// converted to an \c int64_t.
uint32_t RuleIdx;
std::string RuleId;
std::string DiagnosticMessage;
llvm::SmallVector<CharSourceRange, 8> Locations;
llvm::SmallVector<ThreadFlow, 8> ThreadFlows;
SarifResult() = delete;
explicit SarifResult(uint32_t RuleIdx) : RuleIdx(RuleIdx) {}
public:
static SarifResult create(uint32_t RuleIdx) { return SarifResult{RuleIdx}; }
SarifResult setIndex(uint32_t Idx) {
RuleIdx = Idx;
return *this;
}
SarifResult setRuleId(llvm::StringRef Id) {
RuleId = Id.str();
return *this;
}
SarifResult setDiagnosticMessage(llvm::StringRef Message) {
DiagnosticMessage = Message.str();
return *this;
}
SarifResult setLocations(llvm::ArrayRef<CharSourceRange> DiagLocs) {
#ifndef NDEBUG
for (const auto &Loc : DiagLocs) {
assert(Loc.isCharRange() &&
"SARIF Results require character granular source ranges!");
}
#endif
Locations.assign(DiagLocs.begin(), DiagLocs.end());
return *this;
}
SarifResult setThreadFlows(llvm::ArrayRef<ThreadFlow> ThreadFlowResults) {
ThreadFlows.assign(ThreadFlowResults.begin(), ThreadFlowResults.end());
return *this;
}
};
/// This class handles creating a valid SARIF document given various input
/// attributes. However, it requires an ordering among certain method calls:
///
/// 1. Because every SARIF document must contain at least 1 \c run, callers
/// must ensure that \ref SarifDocumentWriter::createRun is is called before
/// any other methods.
/// 2. If SarifDocumentWriter::endRun is called, callers MUST call
/// SarifDocumentWriter::createRun, before invoking any of the result
/// aggregation methods such as SarifDocumentWriter::appendResult etc.
class SarifDocumentWriter {
private:
const llvm::StringRef SchemaURI{
"https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/"
"sarif-schema-2.1.0.json"};
const llvm::StringRef SchemaVersion{"2.1.0"};
/// \internal
/// Return a pointer to the current tool. Asserts that a run exists.
llvm::json::Object &getCurrentTool();
/// \internal
/// Checks if there is a run associated with this document.
///
/// \return true on success
bool hasRun() const;
/// \internal
/// Reset portions of the internal state so that the document is ready to
/// receive data for a new run.
void reset();
/// \internal
/// Return a mutable reference to the current run, after asserting it exists.
///
/// \note It is undefined behavior to call this if a run does not exist in
/// the SARIF document.
llvm::json::Object &getCurrentRun();
/// Create a code flow object for the given threadflows.
/// See \ref ThreadFlow.
///
/// \note It is undefined behavior to call this if a run does not exist in
/// the SARIF document.
llvm::json::Object
createCodeFlow(const llvm::ArrayRef<ThreadFlow> ThreadFlows);
/// Add the given threadflows to the ones this SARIF document knows about.
llvm::json::Array
createThreadFlows(const llvm::ArrayRef<ThreadFlow> ThreadFlows);
/// Add the given \ref CharSourceRange to the SARIF document as a physical
/// location, with its corresponding artifact.
llvm::json::Object createPhysicalLocation(const CharSourceRange &R);
public:
SarifDocumentWriter() = delete;
/// Create a new empty SARIF document with the given source manager.
SarifDocumentWriter(const SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
/// Release resources held by this SARIF document.
~SarifDocumentWriter() = default;
/// Create a new run with which any upcoming analysis will be associated.
/// Each run requires specifying the tool that is generating reporting items.
void createRun(const llvm::StringRef ShortToolName,
const llvm::StringRef LongToolName,
const llvm::StringRef ToolVersion = CLANG_VERSION_STRING);
/// If there is a current run, end it.
///
/// This method collects various book-keeping required to clear and close
/// resources associated with the current run, but may also allocate some
/// for the next run.
///
/// Calling \ref endRun before associating a run through \ref createRun leads
/// to undefined behaviour.
void endRun();
/// Associate the given rule with the current run.
///
/// Returns an integer rule index for the created rule that is unique within
/// the current run, which can then be used to create a \ref SarifResult
/// to add to the current run. Note that a rule must exist before being
/// referenced by a result.
///
/// \pre
/// There must be a run associated with the document, failing to do so will
/// cause undefined behaviour.
size_t createRule(const SarifRule &Rule);
/// Append a new result to the currently in-flight run.
///
/// \pre
/// There must be a run associated with the document, failing to do so will
/// cause undefined behaviour.
/// \pre
/// \c RuleIdx used to create the result must correspond to a rule known by
/// the SARIF document. It must be the value returned by a previous call
/// to \ref createRule.
void appendResult(const SarifResult &SarifResult);
/// Return the SARIF document in its current state.
/// Calling this will trigger a copy of the internal state including all
/// reported diagnostics, resulting in an expensive call.
llvm::json::Object createDocument();
private:
/// Source Manager to use for the current SARIF document.
const SourceManager &SourceMgr;
/// Flag to track the state of this document:
/// A closed document is one on which a new runs must be created.
/// This could be a document that is freshly created, or has recently
/// finished writing to a previous run.
bool Closed = true;
/// A sequence of SARIF runs.
/// Each run object describes a single run of an analysis tool and contains
/// the output of that run.
///
/// Reference: <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317484">run object</a>
llvm::json::Array Runs;
/// The list of rules associated with the most recent active run. These are
/// defined using the diagnostics passed to the SarifDocument. Each rule
/// need not be unique through the result set. E.g. there may be several
/// 'syntax' errors throughout code under analysis, each of which has its
/// own specific diagnostic message (and consequently, RuleId). Rules are
/// also known as "reportingDescriptor" objects in SARIF.
///
/// Reference: <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317556">rules property</a>
llvm::SmallVector<SarifRule, 32> CurrentRules;
/// The list of artifacts that have been encountered on the most recent active
/// run. An artifact is defined in SARIF as a sequence of bytes addressable
/// by a URI. A common example for clang's case would be files named by
/// filesystem paths.
llvm::StringMap<detail::SarifArtifact> CurrentArtifacts;
};
} // namespace clang
#endif // LLVM_CLANG_BASIC_SARIF_H

View File

@ -36,7 +36,8 @@ enum ClangFlags {
FC1Option = (1 << 15),
FlangOnlyOption = (1 << 16),
DXCOption = (1 << 17),
Ignored = (1 << 18),
CLDXCOption = (1 << 18),
Ignored = (1 << 19),
};
enum ID {

View File

@ -53,6 +53,10 @@ def CC1AsOption : OptionFlag;
// are made available when the driver is running in DXC compatibility mode.
def DXCOption : OptionFlag;
// CLDXCOption - This is a cl.exe/dxc.exe compatibility option. Options with this flag
// are made available when the driver is running in CL/DXC compatibility mode.
def CLDXCOption : OptionFlag;
// NoDriverOption - This option should not be accepted by the driver.
def NoDriverOption : OptionFlag;
@ -1140,6 +1144,12 @@ def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>;
def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use Apple's kernel extensions ABI">,
MarshallingInfoFlag<LangOpts<"AppleKext">>;
def fstrict_flex_arrays_EQ : Joined<["-"], "fstrict-flex-arrays=">,Group<f_Group>,
MetaVarName<"<n>">, Values<"0,1,2">,
LangOpts<"StrictFlexArrays">,
Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict definition of flexible arrays">,
MarshallingInfoInt<LangOpts<"StrictFlexArrays">>;
defm apple_pragma_pack : BoolFOption<"apple-pragma-pack",
LangOpts<"ApplePragmaPack">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Enable Apple gcc-compatible #pragma pack handling">,
@ -1183,9 +1193,13 @@ defm coroutines_ts : BoolFOption<"coroutines-ts",
PosFlag<SetTrue, [CC1Option], "Enable support for the C++ Coroutines TS">,
NegFlag<SetFalse>>;
defm unstable : BoolFOption<"unstable",
LangOpts<"Unstable">, DefaultFalse,
PosFlag<SetTrue, [CC1Option, CoreOption], "Enable unstable and experimental features">,
defm experimental_library : BoolFOption<"experimental-library",
LangOpts<"ExperimentalLibrary">, DefaultFalse,
PosFlag<SetTrue, [CC1Option, CoreOption], "Control whether unstable and experimental library features are enabled. "
"This option enables various library features that are either experimental (also known as TSes), or have been "
"but are not stable yet in the selected Standard Library implementation. It is not recommended to use this option "
"in production code, since neither ABI nor API stability are guaranteed. This is intended to provide a preview "
"of features that will ship in the future for experimentation purposes">,
NegFlag<SetFalse>>;
def fembed_offload_object_EQ : Joined<["-"], "fembed-offload-object=">,
@ -1333,6 +1347,15 @@ def fprofile_list_EQ : Joined<["-"], "fprofile-list=">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Filename defining the list of functions/files to instrument">,
MarshallingInfoStringVector<LangOpts<"ProfileListFiles">>;
def fprofile_function_groups : Joined<["-"], "fprofile-function-groups=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<N>">,
HelpText<"Partition functions into N groups and select only functions in group i to be instrumented using -fprofile-selected-function-group">,
MarshallingInfoInt<CodeGenOpts<"ProfileTotalFunctionGroups">, "1">;
def fprofile_selected_function_group :
Joined<["-"], "fprofile-selected-function-group=">, Group<f_Group>,
Flags<[CC1Option]>, MetaVarName<"<i>">,
HelpText<"Partition functions into N groups using -fprofile-function-groups and select only functions in group i to be instrumented. The valid range is 0 to N-1 inclusive">,
MarshallingInfoInt<CodeGenOpts<"ProfileSelectedFunctionGroup">>;
def fswift_async_fp_EQ : Joined<["-"], "fswift-async-fp=">,
Group<f_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>, MetaVarName<"<option>">,
HelpText<"Control emission of Swift async extended frame info">,
@ -2848,6 +2871,15 @@ def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Grou
HelpText<"Minimum time granularity (in microseconds) traced by time profiler">,
Flags<[CC1Option, CoreOption]>,
MarshallingInfoInt<FrontendOpts<"TimeTraceGranularity">, "500u">;
def ftime_trace_EQ : Joined<["-"], "ftime-trace=">, Group<f_Group>,
HelpText<"Turn on time profiler. Generates JSON file based on output filename. "
"Specify the path which stores the tracing output file.">,
DocBrief<[{
Turn on time profiler. Generates JSON file based on output filename. Results
can be analyzed with chrome://tracing or `Speedscope App
<https://www.speedscope.app>`_ for flamegraph visualization.}]>,
Flags<[CC1Option, CoreOption]>,
MarshallingInfoString<FrontendOpts<"TimeTracePath">>;
def fproc_stat_report : Joined<["-"], "fproc-stat-report">, Group<f_Group>,
HelpText<"Print subprocess statistics">;
def fproc_stat_report_EQ : Joined<["-"], "fproc-stat-report=">, Group<f_Group>,
@ -5556,8 +5588,8 @@ def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">,
def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
HelpText<"Change diagnostic formatting to match IDE and command line tools">,
Values<"clang,msvc,vi">,
NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", "MSVC", "Vi"]>,
Values<"clang,msvc,vi,sarif,SARIF">,
NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", "MSVC", "Vi", "SARIF", "SARIF"]>,
MarshallingInfoEnum<DiagnosticOpts<"Format">, "Clang">;
def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
HelpText<"Print diagnostic category">,
@ -6327,7 +6359,7 @@ def defsym : Separate<["-"], "defsym">,
// clang-cl Options
//===----------------------------------------------------------------------===//
def cl_Group : OptionGroup<"<clang-cl options>">, Flags<[CLOption]>,
def cl_Group : OptionGroup<"<clang-cl options>">, Flags<[CLDXCOption]>,
HelpText<"CL.EXE COMPATIBILITY OPTIONS">;
def cl_compile_Group : OptionGroup<"<clang-cl compile-only options>">,
@ -6357,6 +6389,9 @@ class CLIgnoredJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
class CLJoinedOrSeparate<string name> : Option<["/", "-"], name,
KIND_JOINED_OR_SEPARATE>, Group<cl_Group>, Flags<[CLOption, NoXarchOption]>;
class CLDXCJoinedOrSeparate<string name> : Option<["/", "-"], name,
KIND_JOINED_OR_SEPARATE>, Group<cl_Group>, Flags<[CLDXCOption, NoXarchOption]>;
class CLCompileJoinedOrSeparate<string name> : Option<["/", "-"], name,
KIND_JOINED_OR_SEPARATE>, Group<cl_compile_Group>,
Flags<[CLOption, NoXarchOption]>;
@ -6434,7 +6469,7 @@ def _SLASH_help : CLFlag<"help">, Alias<help>,
def _SLASH_HELP : CLFlag<"HELP">, Alias<help>;
def _SLASH_hotpatch : CLFlag<"hotpatch">, Alias<fms_hotpatch>,
HelpText<"Create hotpatchable image">;
def _SLASH_I : CLJoinedOrSeparate<"I">,
def _SLASH_I : CLDXCJoinedOrSeparate<"I">,
HelpText<"Add directory to include search path">, MetaVarName<"<dir>">,
Alias<I>;
def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,

View File

@ -786,7 +786,7 @@ struct FormatStyle {
};
/// The template declaration breaking style to use.
/// \version 7
/// \version 3.4
BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations;
/// A vector of strings that should be interpreted as attributes/qualifiers

View File

@ -499,6 +499,9 @@ class FrontendOptions {
/// Minimum time granularity (in microseconds) traced by time profiler.
unsigned TimeTraceGranularity;
/// Path which stores the output files for -ftime-trace
std::string TimeTracePath;
public:
FrontendOptions()
: DisableFree(false), RelocatablePCH(false), ShowHelp(false),

View File

@ -1019,6 +1019,10 @@ class CodeCompleteConsumer {
/// for which we only have a function prototype.
CK_FunctionType,
/// The candidate is a variable or expression of function type
/// for which we have the location of the prototype declaration.
CK_FunctionProtoTypeLoc,
/// The candidate is a template, template arguments are being completed.
CK_Template,
@ -1043,6 +1047,10 @@ class CodeCompleteConsumer {
/// when Kind == CK_FunctionType.
const FunctionType *Type;
/// The location of the function prototype that describes the entity being
/// called, when Kind == CK_FunctionProtoTypeLoc.
FunctionProtoTypeLoc ProtoTypeLoc;
/// The template overload candidate, available when
/// Kind == CK_Template.
const TemplateDecl *Template;
@ -1068,6 +1076,11 @@ class CodeCompleteConsumer {
assert(Type != nullptr);
}
OverloadCandidate(FunctionProtoTypeLoc Prototype)
: Kind(CK_FunctionProtoTypeLoc), ProtoTypeLoc(Prototype) {
assert(!Prototype.isNull());
}
OverloadCandidate(const RecordDecl *Aggregate)
: Kind(CK_Aggregate), AggregateType(Aggregate) {
assert(Aggregate != nullptr);
@ -1093,6 +1106,11 @@ class CodeCompleteConsumer {
/// function is stored.
const FunctionType *getFunctionType() const;
/// Retrieve the function ProtoTypeLoc candidate.
/// This can be called for any Kind, but returns null for kinds
/// other than CK_FunctionProtoTypeLoc.
const FunctionProtoTypeLoc getFunctionProtoTypeLoc() const;
const TemplateDecl *getTemplate() const {
assert(getKind() == CK_Template && "Not a template");
return Template;

View File

@ -2281,6 +2281,11 @@ class Sema final {
return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
}
/// Is the module scope we are an interface?
bool currentModuleIsInterface() const {
return ModuleScopes.empty() ? false : ModuleScopes.back().ModuleInterface;
}
/// Get the module owning an entity.
Module *getOwningModule(const Decl *Entity) {
return Entity->getOwningModule();

View File

@ -119,6 +119,9 @@ class ConstraintManager {
const char *NL, unsigned int Space,
bool IsDot) const = 0;
virtual void printValue(raw_ostream &Out, ProgramStateRef State,
SymbolRef Sym) {}
/// Convenience method to query the state to see if a symbol is null or
/// not null, or if neither assumption can be made.
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {

View File

@ -617,6 +617,11 @@ class ExprEngine {
return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
}
/// Retreives which element is being constructed in a non POD type array.
static Optional<unsigned>
getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx);
/// By looking at a certain item that may be potentially part of an object's
/// ConstructionContext, retrieve such object's location. A particular
/// statement can be transparently passed as \p Item in most cases.
@ -708,10 +713,19 @@ class ExprEngine {
/// fully implemented it sometimes indicates that it failed via its
/// out-parameter CallOpts; in such cases a fake temporary region is
/// returned, which is better than nothing but does not represent
/// the actual behavior of the program.
SVal computeObjectUnderConstruction(
const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
const ConstructionContext *CC, EvalCallOptions &CallOpts);
/// the actual behavior of the program. The Idx parameter is used if we
/// construct an array of objects. In that case it points to the index
/// of the continous memory region.
/// E.g.:
/// For `int arr[4]` this index can be 0,1,2,3.
/// For `int arr2[3][3]` this index can be 0,1,...,7,8.
/// A multi-dimensional array is also a continous memory location in a
/// row major order, so for arr[0][0] Idx is 0 and for arr[2][2] Idx is 8.
SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State,
const LocationContext *LCtx,
const ConstructionContext *CC,
EvalCallOptions &CallOpts,
unsigned Idx = 0);
/// Update the program state with all the path-sensitive information
/// that's necessary to perform construction of an object with a given
@ -724,12 +738,16 @@ class ExprEngine {
/// A convenient wrapper around computeObjectUnderConstruction
/// and updateObjectsUnderConstruction.
std::pair<ProgramStateRef, SVal> handleConstructionContext(
const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
const ConstructionContext *CC, EvalCallOptions &CallOpts) {
SVal V = computeObjectUnderConstruction(E, State, LCtx, CC, CallOpts);
return std::make_pair(
updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts), V);
std::pair<ProgramStateRef, SVal>
handleConstructionContext(const Expr *E, ProgramStateRef State,
const LocationContext *LCtx,
const ConstructionContext *CC,
EvalCallOptions &CallOpts, unsigned Idx = 0) {
SVal V = computeObjectUnderConstruction(E, State, LCtx, CC, CallOpts, Idx);
State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts);
return std::make_pair(State, V);
}
private:
@ -796,6 +814,15 @@ class ExprEngine {
const ExplodedNode *Pred,
const EvalCallOptions &CallOpts = {});
/// Checks whether our policies allow us to inline a non-POD type array
/// construction.
bool shouldInlineArrayConstruction(const ArrayType *Type);
/// Checks whether we construct an array of non-POD type, and decides if the
/// constructor should be inkoved once again.
bool shouldRepeatCtorCall(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx);
void inlineCall(WorkList *WList, const CallEvent &Call, const Decl *D,
NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State);
@ -838,7 +865,7 @@ class ExprEngine {
const Expr *InitWithAdjustments, const Expr *Result = nullptr,
const SubRegion **OutRegionWithAdjustments = nullptr);
/// Returns a region representing the first element of a (possibly
/// Returns a region representing the `Idx`th element of a (possibly
/// multi-dimensional) array, for the purposes of element construction or
/// destruction.
///
@ -846,8 +873,8 @@ class ExprEngine {
///
/// If the type is not an array type at all, the original value is returned.
/// Otherwise the "IsArray" flag is set.
static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
QualType &Ty, bool &IsArray);
static SVal makeElementRegion(ProgramStateRef State, SVal LValue,
QualType &Ty, bool &IsArray, unsigned Idx = 0);
/// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
/// block to find the constructor expression that directly constructed into
@ -878,6 +905,17 @@ class ExprEngine {
const ObjCForCollectionStmt *O,
const LocationContext *LC);
private:
/// Assuming we construct an array of non-POD types, this method allows us
/// to store which element is to be constructed next.
static ProgramStateRef
setIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx, unsigned Idx);
static ProgramStateRef
removeIndexOfElementToConstruct(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx);
/// Store the location of a C++ object corresponding to a statement
/// until the statement is actually encountered. For example, if a DeclStmt
/// has CXXConstructExpr as its initializer, the object would be considered

View File

@ -1364,6 +1364,7 @@ class MemRegionManager {
~MemRegionManager();
ASTContext &getContext() { return Ctx; }
const ASTContext &getContext() const { return Ctx; }
llvm::BumpPtrAllocator &getAllocator() { return A; }

View File

@ -75,39 +75,6 @@ class SValBuilder {
/// The width of the scalar type used for array indices.
const unsigned ArrayIndexWidth;
SVal evalCastKind(UndefinedVal V, QualType CastTy, QualType OriginalTy);
SVal evalCastKind(UnknownVal V, QualType CastTy, QualType OriginalTy);
SVal evalCastKind(Loc V, QualType CastTy, QualType OriginalTy);
SVal evalCastKind(NonLoc V, QualType CastTy, QualType OriginalTy);
SVal evalCastSubKind(loc::ConcreteInt V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(loc::GotoLabel V, QualType CastTy, QualType OriginalTy);
SVal evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::CompoundVal V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::ConcreteInt V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::LazyCompoundVal V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::LocAsInteger V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
QualType OriginalTy);
SVal evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
QualType OriginalTy);
/// Reduce cast expression by removing redundant intermediate casts.
/// E.g.
/// - (char)(short)(int x) -> (char)(int x)
/// - (int)(int x) -> int x
///
/// \param V -- SymbolVal, which pressumably contains SymbolCast or any symbol
/// that is applicable for cast operation.
/// \param CastTy -- QualType, which `V` shall be cast to.
/// \return SVal with simplified cast expression.
/// \note: Currently only support integral casts.
nonloc::SymbolVal simplifySymbolCast(nonloc::SymbolVal V, QualType CastTy);
public:
SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
ProgramStateManager &stateMgr);

View File

@ -169,6 +169,11 @@ class SVal {
/// should continue to the base regions if the region is not symbolic.
SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
/// If this SVal is loc::ConcreteInt or nonloc::ConcreteInt,
/// return a pointer to APSInt which is held in it.
/// Otherwise, return nullptr.
const llvm::APSInt *getAsInteger() const;
const MemRegion *getAsRegion() const;
/// printJson - Pretty-prints in JSON format.

View File

@ -68,7 +68,9 @@ struct FullDependenciesResult {
class DependencyScanningTool {
public:
/// Construct a dependency scanning tool.
DependencyScanningTool(DependencyScanningService &Service);
DependencyScanningTool(DependencyScanningService &Service,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
llvm::vfs::createPhysicalFileSystem());
/// Print out the dependency information into a string using the dependency
/// file format that is specified in the options (-MD is the default) and

View File

@ -52,7 +52,8 @@ class DependencyConsumer {
/// using the regular processing run.
class DependencyScanningWorker {
public:
DependencyScanningWorker(DependencyScanningService &Service);
DependencyScanningWorker(DependencyScanningService &Service,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
/// Run the dependency scanning tool for a given clang driver command-line,
/// and report the discovered dependencies to the provided consumer. If \p

View File

@ -50,7 +50,7 @@ struct IncludeStyle {
/// Dependent on the value, multiple ``#include`` blocks can be sorted
/// as one and divided based on category.
/// \version 7
/// \version 6
IncludeBlocksStyle IncludeBlocks;
/// See documentation of ``IncludeCategories``.
@ -114,7 +114,7 @@ struct IncludeStyle {
/// Priority: 1
/// SortPriority: 0
/// \endcode
/// \version 7
/// \version 3.8
std::vector<IncludeCategory> IncludeCategories;
/// Specify a regular expression of suffixes that are allowed in the
@ -128,7 +128,7 @@ struct IncludeStyle {
///
/// For example, if configured to "(_test)?$", then a header a.h would be seen
/// as the "main" include in both a.cc and a_test.cc.
/// \version 7
/// \version 3.9
std::string IncludeIsMainRegex;
/// Specify a regular expression for files being formatted
@ -149,7 +149,7 @@ struct IncludeStyle {
/// also being respected in later phase). Without this option set,
/// ``ClassImpl.hpp`` would not have the main include file put on top
/// before any other include.
/// \version 7
/// \version 10
std::string IncludeIsMainSourceRegex;
};

View File

@ -13,6 +13,7 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/Nodes.h"
#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
#include "clang/Tooling/Syntax/Tree.h"
namespace clang {
@ -21,19 +22,21 @@ namespace syntax {
/// Build a syntax tree for the main file.
/// This usually covers the whole TranslationUnitDecl, but can be restricted by
/// the ASTContext's traversal scope.
syntax::TranslationUnit *buildSyntaxTree(Arena &A, ASTContext &Context);
syntax::TranslationUnit *
buildSyntaxTree(Arena &A, TokenBufferTokenManager &TBTM, ASTContext &Context);
// Create syntax trees from subtrees not backed by the source code.
// Synthesis of Leafs
/// Create `Leaf` from token with `Spelling` and assert it has the desired
/// `TokenKind`.
syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K,
StringRef Spelling);
syntax::Leaf *createLeaf(syntax::Arena &A, TokenBufferTokenManager &TBTM,
tok::TokenKind K, StringRef Spelling);
/// Infer the token spelling from its `TokenKind`, then create `Leaf` from
/// this token
syntax::Leaf *createLeaf(syntax::Arena &A, tok::TokenKind K);
syntax::Leaf *createLeaf(syntax::Arena &A, TokenBufferTokenManager &TBTM,
tok::TokenKind K);
// Synthesis of Trees
/// Creates the concrete syntax node according to the specified `NodeKind` `K`.
@ -44,7 +47,8 @@ createTree(syntax::Arena &A,
syntax::NodeKind K);
// Synthesis of Syntax Nodes
syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A);
syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A,
TokenBufferTokenManager &TBTM);
/// Creates a completely independent copy of `N` with its macros expanded.
///
@ -52,7 +56,9 @@ syntax::EmptyStatement *createEmptyStatement(syntax::Arena &A);
/// * Detached, i.e. `Parent == NextSibling == nullptr` and
/// `Role == Detached`.
/// * Synthesized, i.e. `Original == false`.
syntax::Node *deepCopyExpandingMacros(syntax::Arena &A, const syntax::Node *N);
syntax::Node *deepCopyExpandingMacros(syntax::Arena &A,
TokenBufferTokenManager &TBTM,
const syntax::Node *N);
} // namespace syntax
} // namespace clang
#endif

View File

@ -13,6 +13,7 @@
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Syntax/Nodes.h"
#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
#include "clang/Tooling/Syntax/Tree.h"
namespace clang {
@ -20,7 +21,7 @@ namespace syntax {
/// Computes textual replacements required to mimic the tree modifications made
/// to the syntax tree.
tooling::Replacements computeReplacements(const Arena &A,
tooling::Replacements computeReplacements(const TokenBufferTokenManager &TBTM,
const syntax::TranslationUnit &TU);
/// Removes a statement or replaces it with an empty statement where one is
@ -29,7 +30,8 @@ tooling::Replacements computeReplacements(const Arena &A,
/// One can remove `foo();` completely and to remove `bar();` we would need to
/// replace it with an empty statement.
/// EXPECTS: S->canModify() == true
void removeStatement(syntax::Arena &A, syntax::Statement *S);
void removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM,
syntax::Statement *S);
} // namespace syntax
} // namespace clang

View File

@ -21,13 +21,8 @@
#ifndef LLVM_CLANG_TOOLING_SYNTAX_NODES_H
#define LLVM_CLANG_TOOLING_SYNTAX_NODES_H
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/Token.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/Syntax/Tree.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace syntax {

View File

@ -0,0 +1,70 @@
//===- TokenBufferTokenManager.h -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLING_SYNTAX_TOKEN_BUFFER_TOKEN_MANAGER_H
#define LLVM_CLANG_TOOLING_SYNTAX_TOKEN_BUFFER_TOKEN_MANAGER_H
#include "clang/Tooling/Syntax/TokenManager.h"
#include "clang/Tooling/Syntax/Tokens.h"
namespace clang {
namespace syntax {
/// A TokenBuffer-powered token manager.
/// It tracks the underlying token buffers, source manager, etc.
class TokenBufferTokenManager : public TokenManager {
public:
TokenBufferTokenManager(const TokenBuffer &Tokens,
const LangOptions &LangOpts, SourceManager &SourceMgr)
: Tokens(Tokens), LangOpts(LangOpts), SM(SourceMgr) {}
static bool classof(const TokenManager *N) { return N->kind() == Kind; }
llvm::StringLiteral kind() const override { return Kind; }
llvm::StringRef getText(Key I) const override {
const auto *Token = getToken(I);
assert(Token);
// Handle 'eof' separately, calling text() on it produces an empty string.
// FIXME: this special logic is for syntax::Leaf dump, move it when we
// have a direct way to retrive token kind in the syntax::Leaf.
if (Token->kind() == tok::eof)
return "<eof>";
return Token->text(SM);
}
const syntax::Token *getToken(Key I) const {
return reinterpret_cast<const syntax::Token *>(I);
}
SourceManager &sourceManager() { return SM; }
const SourceManager &sourceManager() const { return SM; }
const TokenBuffer &tokenBuffer() const { return Tokens; }
private:
// This manager is powered by the TokenBuffer.
static constexpr llvm::StringLiteral Kind = "TokenBuffer";
/// Add \p Buffer to the underlying source manager, tokenize it and store the
/// resulting tokens. Used exclusively in `FactoryImpl` to materialize tokens
/// that were not written in user code.
std::pair<FileID, ArrayRef<Token>>
lexBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
friend class FactoryImpl;
const TokenBuffer &Tokens;
const LangOptions &LangOpts;
/// The underlying source manager for the ExtraTokens.
SourceManager &SM;
/// IDs and storage for additional tokenized files.
llvm::DenseMap<FileID, std::vector<Token>> ExtraTokens;
};
} // namespace syntax
} // namespace clang
#endif // LLVM_CLANG_TOOLING_SYNTAX_TOKEN_BUFFER_TOKEN_MANAGER_H

View File

@ -0,0 +1,47 @@
//===- TokenManager.h - Manage Tokens for syntax-tree ------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines Token interfaces for the clang syntax-tree. This is the level of
// abstraction that the syntax-tree uses to operate on Token.
//
// TokenManager decouples the syntax-tree from a particular token
// implementation. For example, a TokenBuffer captured from a clang parser may
// track macro expansions and associate tokens with clang's SourceManager, while
// a clang pseudoparser would use a flat array of raw-lexed tokens in memory.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLING_SYNTAX_TOKEN_MANAGER_H
#define LLVM_CLANG_TOOLING_SYNTAX_TOKEN_MANAGER_H
#include "llvm/ADT/StringRef.h"
#include <cstdint>
namespace clang {
namespace syntax {
/// Defines interfaces for operating "Token" in the clang syntax-tree.
class TokenManager {
public:
virtual ~TokenManager() = default;
/// Describes what the exact class kind of the TokenManager is.
virtual llvm::StringLiteral kind() const = 0;
/// A key to identify a specific token. The token concept depends on the
/// underlying implementation -- it can be a spelled token from the original
/// source file or an expanded token.
/// The syntax-tree Leaf node holds a Key.
using Key = uintptr_t;
virtual llvm::StringRef getText(Key K) const = 0;
};
} // namespace syntax
} // namespace clang
#endif // LLVM_CLANG_TOOLING_SYNTAX_TOKEN_MANAGER_H

View File

@ -27,7 +27,6 @@
#ifndef LLVM_CLANG_TOOLING_SYNTAX_TOKENS_H
#define LLVM_CLANG_TOOLING_SYNTAX_TOKENS_H
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"

View File

@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
// Defines the basic structure of the syntax tree. There are two kinds of nodes:
// - leaf nodes correspond to a token in the expanded token stream,
// - leaf nodes correspond to tokens,
// - tree nodes correspond to language grammar constructs.
//
// The tree is initially built from an AST. Each node of a newly built tree
@ -21,48 +21,22 @@
#ifndef LLVM_CLANG_TOOLING_SYNTAX_TREE_H
#define LLVM_CLANG_TOOLING_SYNTAX_TREE_H
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "clang/Tooling/Syntax/TokenManager.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include <cstdint>
#include <iterator>
#include <vector>
namespace clang {
namespace syntax {
/// A memory arena for syntax trees. Also tracks the underlying token buffers,
/// source manager, etc.
/// A memory arena for syntax trees.
// FIXME: use BumpPtrAllocator directly.
class Arena {
public:
Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
const TokenBuffer &Tokens);
const SourceManager &getSourceManager() const { return SourceMgr; }
const LangOptions &getLangOptions() const { return LangOpts; }
const TokenBuffer &getTokenBuffer() const;
llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
private:
/// Add \p Buffer to the underlying source manager, tokenize it and store the
/// resulting tokens. Used exclusively in `FactoryImpl` to materialize tokens
/// that were not written in user code.
std::pair<FileID, ArrayRef<Token>>
lexBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
friend class FactoryImpl;
private:
SourceManager &SourceMgr;
const LangOptions &LangOpts;
const TokenBuffer &Tokens;
/// IDs and storage for additional tokenized files.
llvm::DenseMap<FileID, std::vector<Token>> ExtraTokens;
/// Keeps all the allocated nodes and their intermediate data structures.
llvm::BumpPtrAllocator Allocator;
};
@ -122,9 +96,9 @@ class Node {
Node *getPreviousSibling() { return PreviousSibling; }
/// Dumps the structure of a subtree. For debugging and testing purposes.
std::string dump(const SourceManager &SM) const;
std::string dump(const TokenManager &SM) const;
/// Dumps the tokens forming this subtree.
std::string dumpTokens(const SourceManager &SM) const;
std::string dumpTokens(const TokenManager &SM) const;
/// Asserts invariants on this node of the tree and its immediate children.
/// Will not recurse into the subtree. No-op if NDEBUG is set.
@ -153,16 +127,17 @@ class Node {
unsigned CanModify : 1;
};
/// A leaf node points to a single token inside the expanded token stream.
/// A leaf node points to a single token.
// FIXME: add TokenKind field (borrow some bits from the Node::kind).
class Leaf final : public Node {
public:
Leaf(const Token *T);
Leaf(TokenManager::Key K);
static bool classof(const Node *N);
const Token *getToken() const { return Tok; }
TokenManager::Key getTokenKey() const { return K; }
private:
const Token *Tok;
TokenManager::Key K;
};
/// A node that has children and represents a syntactic language construct.

View File

@ -71,10 +71,17 @@ module Clang_Basic {
textual header "Basic/RISCVVTypes.def"
textual header "Basic/Sanitizers.def"
textual header "Basic/TargetCXXABI.def"
textual header "Basic/TokenKinds.def"
module * { export * }
}
module Clang_Basic_TokenKinds {
requires cplusplus
header "Basic/TokenKinds.h"
textual header "Basic/TokenKinds.def"
export *
}
module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } }
module Clang_Config { requires cplusplus umbrella "Config" module * { export * } }
@ -182,5 +189,8 @@ module Clang_ToolingCore {
module Clang_ToolingInclusions {
requires cplusplus
umbrella "Tooling/Inclusions" module * { export * }
umbrella "Tooling/Inclusions"
textual header "Tooling/Inclusions/CSymbolMap.inc"
textual header "Tooling/Inclusions/StdSymbolMap.inc"
module * { export * }
}

View File

@ -3109,6 +3109,11 @@ Error ASTNodeImporter::ImportTemplateInformation(
case FunctionDecl::TK_FunctionTemplate:
return Error::success();
case FunctionDecl::TK_DependentNonTemplate:
if (Expected<FunctionDecl *> InstFDOrErr =
import(FromFD->getInstantiatedFromDecl()))
ToFD->setInstantiatedFromDecl(*InstFDOrErr);
return Error::success();
case FunctionDecl::TK_MemberSpecialization: {
TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();

View File

@ -3717,8 +3717,13 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
if (TemplateOrSpecialization.isNull())
return TK_NonTemplate;
if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
if (isa<FunctionDecl>(ND))
return TK_DependentNonTemplate;
assert(isa<FunctionTemplateDecl>(ND) &&
"No other valid types in NamedDecl");
return TK_FunctionTemplate;
}
if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
return TK_MemberSpecialization;
if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
@ -3759,15 +3764,28 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
}
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
return dyn_cast_or_null<FunctionTemplateDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
void FunctionDecl::setDescribedFunctionTemplate(
FunctionTemplateDecl *Template) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
TemplateOrSpecialization = Template;
}
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
assert(TemplateOrSpecialization.isNull() &&
"Function is already a specialization");
TemplateOrSpecialization = FD;
}
FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
return dyn_cast_or_null<FunctionDecl>(
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())

View File

@ -283,8 +283,9 @@ unsigned Decl::getTemplateDepth() const {
return cast<Decl>(DC)->getTemplateDepth();
}
const DeclContext *Decl::getParentFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
const DeclContext *Decl::getParentFunctionOrMethod(bool LexicalParent) const {
for (const DeclContext *DC = LexicalParent ? getLexicalDeclContext()
: getDeclContext();
DC && !DC->isTranslationUnit() && !DC->isNamespace();
DC = DC->getParent())
if (DC->isFunctionOrMethod())

View File

@ -2410,7 +2410,7 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const {
return false;
QualType ParamType = getParamDecl(0)->getType();
if (!isa<RValueReferenceType>(ParamType))
if (!ParamType->isRValueReferenceType())
return false;
ParamType = ParamType->getPointeeType();

View File

@ -1007,10 +1007,10 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
}
if (auto *Def = D->getDefinition()) {
if (D->hasAttr<FinalAttr>()) {
Out << " final";
}
if (D->hasDefinition()) {
if (D->hasAttr<FinalAttr>()) {
Out << " final";
}
}
if (D->isCompleteDefinition()) {

View File

@ -11595,9 +11595,15 @@ static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {
// conservative with the last element in structs (if it's an array), so our
// current behavior is more compatible than an explicit list approach would
// be.
int StrictFlexArraysLevel = Ctx.getLangOpts().StrictFlexArrays;
return LVal.InvalidBase &&
Designator.Entries.size() == Designator.MostDerivedPathLength &&
Designator.MostDerivedIsArrayElement &&
(Designator.isMostDerivedAnUnsizedArray() ||
Designator.getMostDerivedArraySize() == 0 ||
(Designator.getMostDerivedArraySize() == 1 &&
StrictFlexArraysLevel < 2) ||
StrictFlexArraysLevel == 0) &&
isDesignatorAtObjectEnd(Ctx, LVal);
}

View File

@ -1720,6 +1720,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
}
}
if (!D->isInlineSpecified() && D->isInlined()) {
OS << " implicit-inline";
}
// Since NumParams comes from the FunctionProtoType of the FunctionDecl and
// the Params are set later, it is possible for a dump during debugging to
// encounter a FunctionDecl that has been created but hasn't been assigned

View File

@ -14,7 +14,9 @@
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/Support/Debug.h"
#include <cassert>
#include <memory>
#include <utility>
@ -293,6 +295,17 @@ BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
return substituteBoolValue(*ConstraintsIT->second, SubstitutionsCache);
}
void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
llvm::DenseSet<BoolValue *> Constraints = {&Token};
llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
{&getBoolLiteralValue(false), "False"},
{&getBoolLiteralValue(true), "True"}};
llvm::dbgs() << debugString(Constraints, AtomNames);
}
} // namespace dataflow
} // namespace clang

View File

@ -15,10 +15,8 @@
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@ -512,5 +510,9 @@ bool Environment::flowConditionImplies(BoolValue &Val) const {
return DACtx->flowConditionImplies(*FlowConditionToken, Val);
}
void Environment::dump() const {
DACtx->dumpFlowCondition(*FlowConditionToken);
}
} // namespace dataflow
} // namespace clang

View File

@ -17,6 +17,7 @@
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatAdapters.h"
@ -30,6 +31,28 @@ using llvm::AlignStyle;
using llvm::fmt_pad;
using llvm::formatv;
std::string debugString(Solver::Result::Assignment Assignment) {
switch (Assignment) {
case Solver::Result::Assignment::AssignedFalse:
return "False";
case Solver::Result::Assignment::AssignedTrue:
return "True";
}
llvm_unreachable("Booleans can only be assigned true/false");
}
std::string debugString(Solver::Result::Status Status) {
switch (Status) {
case Solver::Result::Status::Satisfiable:
return "Satisfiable";
case Solver::Result::Status::Unsatisfiable:
return "Unsatisfiable";
case Solver::Result::Status::TimedOut:
return "TimedOut";
}
llvm_unreachable("Unhandled SAT check result status");
}
namespace {
class DebugStringGenerator {
@ -80,9 +103,25 @@ class DebugStringGenerator {
return formatv("{0}", fmt_pad(S, Indent, 0));
}
std::string debugString(const llvm::DenseSet<BoolValue *> &Constraints) {
std::vector<std::string> ConstraintsStrings;
ConstraintsStrings.reserve(Constraints.size());
for (BoolValue *Constraint : Constraints) {
ConstraintsStrings.push_back(debugString(*Constraint));
}
llvm::sort(ConstraintsStrings);
std::string Result;
for (const std::string &S : ConstraintsStrings) {
Result += S;
Result += '\n';
}
return Result;
}
/// Returns a string representation of a set of boolean `Constraints` and the
/// `Result` of satisfiability checking on the `Constraints`.
std::string debugString(const std::vector<BoolValue *> &Constraints,
std::string debugString(ArrayRef<BoolValue *> &Constraints,
const Solver::Result &Result) {
auto Template = R"(
Constraints
@ -101,10 +140,9 @@ Constraints
ConstraintsStrings.push_back(debugString(*Constraint));
}
auto StatusString = debugString(Result.getStatus());
auto StatusString = clang::dataflow::debugString(Result.getStatus());
auto Solution = Result.getSolution();
auto SolutionString =
Solution.hasValue() ? "\n" + debugString(Solution.value()) : "";
auto SolutionString = Solution ? "\n" + debugString(Solution.value()) : "";
return formatv(
Template,
@ -127,38 +165,14 @@ Constraints
auto Line = formatv("{0} = {1}",
fmt_align(getAtomName(AtomAssignment.first),
AlignStyle::Left, MaxNameLength),
debugString(AtomAssignment.second));
clang::dataflow::debugString(AtomAssignment.second));
Lines.push_back(Line);
}
llvm::sort(Lines.begin(), Lines.end());
llvm::sort(Lines);
return formatv("{0:$[\n]}", llvm::make_range(Lines.begin(), Lines.end()));
}
/// Returns a string representation of a boolean assignment to true or false.
std::string debugString(Solver::Result::Assignment Assignment) {
switch (Assignment) {
case Solver::Result::Assignment::AssignedFalse:
return "False";
case Solver::Result::Assignment::AssignedTrue:
return "True";
}
llvm_unreachable("Booleans can only be assigned true/false");
}
/// Returns a string representation of the result status of a SAT check.
std::string debugString(Solver::Result::Status Status) {
switch (Status) {
case Solver::Result::Status::Satisfiable:
return "Satisfiable";
case Solver::Result::Status::Unsatisfiable:
return "Unsatisfiable";
case Solver::Result::Status::TimedOut:
return "TimedOut";
}
llvm_unreachable("Unhandled SAT check result status");
}
/// Returns the name assigned to `Atom`, either user-specified or created by
/// default rules (B0, B1, ...).
std::string getAtomName(const AtomicBoolValue *Atom) {
@ -186,8 +200,13 @@ debugString(const BoolValue &B,
}
std::string
debugString(const std::vector<BoolValue *> &Constraints,
const Solver::Result &Result,
debugString(const llvm::DenseSet<BoolValue *> &Constraints,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
return DebugStringGenerator(std::move(AtomNames)).debugString(Constraints);
}
std::string
debugString(ArrayRef<BoolValue *> Constraints, const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
return DebugStringGenerator(std::move(AtomNames))
.debugString(Constraints, Result);

View File

@ -1679,6 +1679,17 @@ void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
return;
}
if (const auto *BO = dyn_cast<BinaryOperator>(Exp)) {
switch (BO->getOpcode()) {
case BO_PtrMemD: // .*
return checkAccess(BO->getLHS(), AK, POK);
case BO_PtrMemI: // ->*
return checkPtAccess(BO->getLHS(), AK, POK);
default:
return;
}
}
if (const auto *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
checkPtAccess(AE->getLHS(), AK, POK);
return;

View File

@ -32,4 +32,4 @@ void clang::quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res) {
Res.push_back(Target[i]);
}
}
}

View File

@ -47,6 +47,11 @@ bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
return SSCL->inSection(Mask, "src", FileName, Category);
}
bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
StringRef Category) const {
return SSCL->inSection(Mask, "mainfile", FileName, Category);
}
bool NoSanitizeList::containsLocation(SanitizerMask Mask, SourceLocation Loc,
StringRef Category) const {
return Loc.isValid() &&

View File

@ -0,0 +1,389 @@
//===-- clang/Basic/Sarif.cpp - SarifDocumentWriter class definition ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declaration of the SARIFDocumentWriter class, and
/// associated builders such as:
/// - \ref SarifArtifact
/// - \ref SarifArtifactLocation
/// - \ref SarifRule
/// - \ref SarifResult
//===----------------------------------------------------------------------===//
#include "clang/Basic/Sarif.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include <string>
#include <utility>
using namespace clang;
using namespace llvm;
using clang::detail::SarifArtifact;
using clang::detail::SarifArtifactLocation;
static StringRef getFileName(const FileEntry &FE) {
StringRef Filename = FE.tryGetRealPathName();
if (Filename.empty())
Filename = FE.getName();
return Filename;
}
/// \name URI
/// @{
/// \internal
/// \brief
/// Return the RFC3986 encoding of the input character.
///
/// \param C Character to encode to RFC3986.
///
/// \return The RFC3986 representation of \c C.
static std::string percentEncodeURICharacter(char C) {
// RFC 3986 claims alpha, numeric, and this handful of
// characters are not reserved for the path component and
// should be written out directly. Otherwise, percent
// encode the character and write that out instead of the
// reserved character.
if (llvm::isAlnum(C) ||
StringRef::npos != StringRef("-._~:@!$&'()*+,;=").find(C))
return std::string(&C, 1);
return "%" + llvm::toHex(StringRef(&C, 1));
}
/// \internal
/// \brief Return a URI representing the given file name.
///
/// \param Filename The filename to be represented as URI.
///
/// \return RFC3986 URI representing the input file name.
static std::string fileNameToURI(StringRef Filename) {
SmallString<32> Ret = StringRef("file://");
// Get the root name to see if it has a URI authority.
StringRef Root = sys::path::root_name(Filename);
if (Root.startswith("//")) {
// There is an authority, so add it to the URI.
Ret += Root.drop_front(2).str();
} else if (!Root.empty()) {
// There is no authority, so end the component and add the root to the URI.
Ret += Twine("/" + Root).str();
}
auto Iter = sys::path::begin(Filename), End = sys::path::end(Filename);
assert(Iter != End && "Expected there to be a non-root path component.");
// Add the rest of the path components, encoding any reserved characters;
// we skip past the first path component, as it was handled it above.
std::for_each(++Iter, End, [&Ret](StringRef Component) {
// For reasons unknown to me, we may get a backslash with Windows native
// paths for the initial backslash following the drive component, which
// we need to ignore as a URI path part.
if (Component == "\\")
return;
// Add the separator between the previous path part and the one being
// currently processed.
Ret += "/";
// URI encode the part.
for (char C : Component) {
Ret += percentEncodeURICharacter(C);
}
});
return std::string(Ret);
}
/// @}
/// \brief Calculate the column position expressed in the number of UTF-8 code
/// points from column start to the source location
///
/// \param Loc The source location whose column needs to be calculated.
/// \param TokenLen Optional hint for when the token is multiple bytes long.
///
/// \return The column number as a UTF-8 aware byte offset from column start to
/// the effective source location.
static unsigned int adjustColumnPos(FullSourceLoc Loc,
unsigned int TokenLen = 0) {
assert(!Loc.isInvalid() && "invalid Loc when adjusting column position");
std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc();
Optional<MemoryBufferRef> Buf =
Loc.getManager().getBufferOrNone(LocInfo.first);
assert(Buf && "got an invalid buffer for the location's file");
assert(Buf->getBufferSize() >= (LocInfo.second + TokenLen) &&
"token extends past end of buffer?");
// Adjust the offset to be the start of the line, since we'll be counting
// Unicode characters from there until our column offset.
unsigned int Off = LocInfo.second - (Loc.getExpansionColumnNumber() - 1);
unsigned int Ret = 1;
while (Off < (LocInfo.second + TokenLen)) {
Off += getNumBytesForUTF8(Buf->getBuffer()[Off]);
Ret++;
}
return Ret;
}
/// \name SARIF Utilities
/// @{
/// \internal
json::Object createMessage(StringRef Text) {
return json::Object{{"text", Text.str()}};
}
/// \internal
/// \pre CharSourceRange must be a token range
static json::Object createTextRegion(const SourceManager &SM,
const CharSourceRange &R) {
FullSourceLoc FirstTokenLoc{R.getBegin(), SM};
FullSourceLoc LastTokenLoc{R.getEnd(), SM};
json::Object Region{{"startLine", FirstTokenLoc.getExpansionLineNumber()},
{"startColumn", adjustColumnPos(FirstTokenLoc)},
{"endColumn", adjustColumnPos(LastTokenLoc)}};
if (FirstTokenLoc != LastTokenLoc) {
Region["endLine"] = LastTokenLoc.getExpansionLineNumber();
}
return Region;
}
static json::Object createLocation(json::Object &&PhysicalLocation,
StringRef Message = "") {
json::Object Ret{{"physicalLocation", std::move(PhysicalLocation)}};
if (!Message.empty())
Ret.insert({"message", createMessage(Message)});
return Ret;
}
static StringRef importanceToStr(ThreadFlowImportance I) {
switch (I) {
case ThreadFlowImportance::Important:
return "important";
case ThreadFlowImportance::Essential:
return "essential";
case ThreadFlowImportance::Unimportant:
return "unimportant";
}
llvm_unreachable("Fully covered switch is not so fully covered");
}
static json::Object
createThreadFlowLocation(json::Object &&Location,
const ThreadFlowImportance &Importance) {
return json::Object{{"location", std::move(Location)},
{"importance", importanceToStr(Importance)}};
}
/// @}
json::Object
SarifDocumentWriter::createPhysicalLocation(const CharSourceRange &R) {
assert(R.isValid() &&
"Cannot create a physicalLocation from invalid SourceRange!");
assert(R.isCharRange() &&
"Cannot create a physicalLocation from a token range!");
FullSourceLoc Start{R.getBegin(), SourceMgr};
const FileEntry *FE = Start.getExpansionLoc().getFileEntry();
assert(FE != nullptr && "Diagnostic does not exist within a valid file!");
const std::string &FileURI = fileNameToURI(getFileName(*FE));
auto I = CurrentArtifacts.find(FileURI);
if (I == CurrentArtifacts.end()) {
uint32_t Idx = static_cast<uint32_t>(CurrentArtifacts.size());
const SarifArtifactLocation &Location =
SarifArtifactLocation::create(FileURI).setIndex(Idx);
const SarifArtifact &Artifact = SarifArtifact::create(Location)
.setRoles({"resultFile"})
.setLength(FE->getSize())
.setMimeType("text/plain");
auto StatusIter = CurrentArtifacts.insert({FileURI, Artifact});
// If inserted, ensure the original iterator points to the newly inserted
// element, so it can be used downstream.
if (StatusIter.second)
I = StatusIter.first;
}
assert(I != CurrentArtifacts.end() && "Failed to insert new artifact");
const SarifArtifactLocation &Location = I->second.Location;
uint32_t Idx = Location.Index.value();
return json::Object{{{"artifactLocation", json::Object{{{"index", Idx}}}},
{"region", createTextRegion(SourceMgr, R)}}};
}
json::Object &SarifDocumentWriter::getCurrentTool() {
assert(!Closed && "SARIF Document is closed. "
"Need to call createRun() before using getcurrentTool!");
// Since Closed = false here, expect there to be at least 1 Run, anything
// else is an invalid state.
assert(!Runs.empty() && "There are no runs associated with the document!");
return *Runs.back().getAsObject()->get("tool")->getAsObject();
}
void SarifDocumentWriter::reset() {
CurrentRules.clear();
CurrentArtifacts.clear();
}
void SarifDocumentWriter::endRun() {
// Exit early if trying to close a closed Document.
if (Closed) {
reset();
return;
}
// Since Closed = false here, expect there to be at least 1 Run, anything
// else is an invalid state.
assert(!Runs.empty() && "There are no runs associated with the document!");
// Flush all the rules.
json::Object &Tool = getCurrentTool();
json::Array Rules;
for (const SarifRule &R : CurrentRules) {
json::Object Rule{
{"name", R.Name},
{"id", R.Id},
{"fullDescription", json::Object{{"text", R.Description}}}};
if (!R.HelpURI.empty())
Rule["helpUri"] = R.HelpURI;
Rules.emplace_back(std::move(Rule));
}
json::Object &Driver = *Tool.getObject("driver");
Driver["rules"] = std::move(Rules);
// Flush all the artifacts.
json::Object &Run = getCurrentRun();
json::Array *Artifacts = Run.getArray("artifacts");
for (const auto &Pair : CurrentArtifacts) {
const SarifArtifact &A = Pair.getValue();
json::Object Loc{{"uri", A.Location.URI}};
if (A.Location.Index.has_value()) {
Loc["index"] = static_cast<int64_t>(A.Location.Index.value());
}
json::Object Artifact;
Artifact["location"] = std::move(Loc);
if (A.Length.has_value())
Artifact["length"] = static_cast<int64_t>(A.Length.value());
if (!A.Roles.empty())
Artifact["roles"] = json::Array(A.Roles);
if (!A.MimeType.empty())
Artifact["mimeType"] = A.MimeType;
if (A.Offset.has_value())
Artifact["offset"] = A.Offset;
Artifacts->push_back(json::Value(std::move(Artifact)));
}
// Clear, reset temporaries before next run.
reset();
// Mark the document as closed.
Closed = true;
}
json::Array
SarifDocumentWriter::createThreadFlows(ArrayRef<ThreadFlow> ThreadFlows) {
json::Object Ret{{"locations", json::Array{}}};
json::Array Locs;
for (const auto &ThreadFlow : ThreadFlows) {
json::Object PLoc = createPhysicalLocation(ThreadFlow.Range);
json::Object Loc = createLocation(std::move(PLoc), ThreadFlow.Message);
Locs.emplace_back(
createThreadFlowLocation(std::move(Loc), ThreadFlow.Importance));
}
Ret["locations"] = std::move(Locs);
return json::Array{std::move(Ret)};
}
json::Object
SarifDocumentWriter::createCodeFlow(ArrayRef<ThreadFlow> ThreadFlows) {
return json::Object{{"threadFlows", createThreadFlows(ThreadFlows)}};
}
void SarifDocumentWriter::createRun(StringRef ShortToolName,
StringRef LongToolName,
StringRef ToolVersion) {
// Clear resources associated with a previous run.
endRun();
// Signify a new run has begun.
Closed = false;
json::Object Tool{
{"driver",
json::Object{{"name", ShortToolName},
{"fullName", LongToolName},
{"language", "en-US"},
{"version", ToolVersion},
{"informationUri",
"https://clang.llvm.org/docs/UsersManual.html"}}}};
json::Object TheRun{{"tool", std::move(Tool)},
{"results", {}},
{"artifacts", {}},
{"columnKind", "unicodeCodePoints"}};
Runs.emplace_back(std::move(TheRun));
}
json::Object &SarifDocumentWriter::getCurrentRun() {
assert(!Closed &&
"SARIF Document is closed. "
"Can only getCurrentRun() if document is opened via createRun(), "
"create a run first");
// Since Closed = false here, expect there to be at least 1 Run, anything
// else is an invalid state.
assert(!Runs.empty() && "There are no runs associated with the document!");
return *Runs.back().getAsObject();
}
size_t SarifDocumentWriter::createRule(const SarifRule &Rule) {
size_t Ret = CurrentRules.size();
CurrentRules.emplace_back(Rule);
return Ret;
}
void SarifDocumentWriter::appendResult(const SarifResult &Result) {
size_t RuleIdx = Result.RuleIdx;
assert(RuleIdx < CurrentRules.size() &&
"Trying to reference a rule that doesn't exist");
json::Object Ret{{"message", createMessage(Result.DiagnosticMessage)},
{"ruleIndex", static_cast<int64_t>(RuleIdx)},
{"ruleId", CurrentRules[RuleIdx].Id}};
if (!Result.Locations.empty()) {
json::Array Locs;
for (auto &Range : Result.Locations) {
Locs.emplace_back(createLocation(createPhysicalLocation(Range)));
}
Ret["locations"] = std::move(Locs);
}
if (!Result.ThreadFlows.empty())
Ret["codeFlows"] = json::Array{createCodeFlow(Result.ThreadFlows)};
json::Object &Run = getCurrentRun();
json::Array *Results = Run.getArray("results");
Results->emplace_back(std::move(Ret));
}
json::Object SarifDocumentWriter::createDocument() {
// Flush all temporaries to their destinations if needed.
endRun();
json::Object Doc{
{"$schema", SchemaURI},
{"version", SchemaVersion},
};
if (!Runs.empty())
Doc["runs"] = json::Array(Runs);
return Doc;
}

View File

@ -250,6 +250,7 @@ bool AMDGPUTargetInfo::initFeatureMap(
break;
case GK_GFX940:
Features["gfx940-insts"] = true;
Features["fp8-insts"] = true;
LLVM_FALLTHROUGH;
case GK_GFX90A:
Features["gfx90a-insts"] = true;

View File

@ -158,8 +158,10 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
}
if (ISAInfo->hasExtension("m")) {
if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
Builder.defineMacro("__riscv_mul");
if (ISAInfo->hasExtension("m")) {
Builder.defineMacro("__riscv_div");
Builder.defineMacro("__riscv_muldiv");
}

View File

@ -35,10 +35,6 @@ namespace CodeGen {
class CodeGenTypes;
class SwiftABIInfo;
namespace swiftcall {
class SwiftAggLowering;
}
// FIXME: All of this stuff should be part of the target interface
// somehow. It is currently here because it is not clear how to factor
// the targets to support this, since the Targets currently live in a

View File

@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "ABIInfo.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"

View File

@ -22,9 +22,6 @@
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
// FIXME: Restructure so we don't have to expose so much stuff.
#include "ABIInfo.h"
namespace llvm {
class Type;
class Value;

View File

@ -618,6 +618,130 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
CXXThreadLocals.clear();
}
/* Build the initializer for a C++20 module:
This is arranged to be run only once regardless of how many times the module
might be included transitively. This arranged by using a control variable.
First we call any initializers for imported modules.
We then call initializers for the Global Module Fragment (if present)
We then call initializers for the current module.
We then call initializers for the Private Module Fragment (if present)
*/
void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
CXXGlobalInits.pop_back();
// We create the function, even if it is empty, since an importer of this
// module will refer to it unconditionally (for the current implementation
// there is no way for the importer to know that an importee does not need
// an initializer to be run).
// Module initializers for imported modules are emitted first.
// Collect the modules that we import
SmallVector<Module *> AllImports;
// Ones that we export
for (auto I : Primary->Exports)
AllImports.push_back(I.getPointer());
// Ones that we only import.
for (Module *M : Primary->Imports)
AllImports.push_back(M);
SmallVector<llvm::Function *, 8> ModuleInits;
for (Module *M : AllImports) {
// No Itanium initializer in module map modules.
if (M->isModuleMapModule())
continue; // TODO: warn of mixed use of module map modules and C++20?
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
SmallString<256> FnName;
{
llvm::raw_svector_ostream Out(FnName);
cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
.mangleModuleInitializer(M, Out);
}
assert(!GetGlobalValue(FnName.str()) &&
"We should only have one use of the initializer call");
llvm::Function *Fn = llvm::Function::Create(
FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
ModuleInits.push_back(Fn);
}
AllImports.clear();
// Add any initializers with specified priority; this uses the same approach
// as EmitCXXGlobalInitFunc().
if (!PrioritizedCXXGlobalInits.empty()) {
SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
PrioritizedCXXGlobalInits.end());
for (SmallVectorImpl<GlobalInitData>::iterator
I = PrioritizedCXXGlobalInits.begin(),
E = PrioritizedCXXGlobalInits.end();
I != E;) {
SmallVectorImpl<GlobalInitData>::iterator PrioE =
std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
for (; I < PrioE; ++I)
ModuleInits.push_back(I->second);
}
PrioritizedCXXGlobalInits.clear();
}
// Now append the ones without specified priority.
for (auto F : CXXGlobalInits)
ModuleInits.push_back(F);
CXXGlobalInits.clear();
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
// We now build the initializer for this module, which has a mangled name
// as per the Itanium ABI . The action of the initializer is guarded so that
// each init is run just once (even though a module might be imported
// multiple times via nested use).
llvm::Function *Fn;
llvm::GlobalVariable *Guard = nullptr;
{
SmallString<256> InitFnName;
llvm::raw_svector_ostream Out(InitFnName);
cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
.mangleModuleInitializer(Primary, Out);
Fn = CreateGlobalInitOrCleanUpFunction(
FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
llvm::GlobalVariable::ExternalLinkage);
Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
llvm::GlobalVariable::InternalLinkage,
llvm::ConstantInt::get(Int8Ty, 0),
InitFnName.str() + "__in_chrg");
}
CharUnits GuardAlign = CharUnits::One();
Guard->setAlignment(GuardAlign.getAsAlign());
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(
Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign));
// We allow for the case that a module object is added to a linked binary
// without a specific call to the the initializer. This also ensure that
// implementation partition initializers are called when the partition
// is not imported as an interface.
AddGlobalCtor(Fn);
// See the comment in EmitCXXGlobalInitFunc about OpenCL global init
// functions.
if (getLangOpts().OpenCL) {
GenKernelArgMetadata(Fn);
Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
}
assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
getLangOpts().GPUAllowDeviceInit);
if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
Fn->addFnAttr("device-init");
}
ModuleInits.clear();
}
static SmallString<128> getTransformedFileName(llvm::Module &M) {
SmallString<128> FileName = llvm::sys::path::filename(M.getName());
@ -650,7 +774,29 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
CXXGlobalInits.pop_back();
if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
// When we import C++20 modules, we must run their initializers first.
SmallVector<llvm::Function *, 8> ModuleInits;
if (CXX20ModuleInits)
for (Module *M : ImportedModules) {
// No Itanium initializer in module map modules.
if (M->isModuleMapModule())
continue;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
SmallString<256> FnName;
{
llvm::raw_svector_ostream Out(FnName);
cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
.mangleModuleInitializer(M, Out);
}
assert(!GetGlobalValue(FnName.str()) &&
"We should only have one use of the initializer call");
llvm::Function *Fn = llvm::Function::Create(
FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
ModuleInits.push_back(Fn);
}
if (ModuleInits.empty() && CXXGlobalInits.empty() &&
PrioritizedCXXGlobalInits.empty())
return;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
@ -676,6 +822,13 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
// Prepend the module inits to the highest priority set.
if (!ModuleInits.empty()) {
for (auto F : ModuleInits)
LocalCXXGlobalInits.push_back(F);
ModuleInits.clear();
}
for (; I < PrioE; ++I)
LocalCXXGlobalInits.push_back(I->second);
@ -685,17 +838,33 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
PrioritizedCXXGlobalInits.clear();
}
if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty())
if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&
CXXGlobalInits.empty())
return;
for (auto F : CXXGlobalInits)
ModuleInits.push_back(F);
CXXGlobalInits.clear();
// Include the filename in the symbol name. Including "sub_" matches gcc
// and makes sure these symbols appear lexicographically behind the symbols
// with priority emitted above.
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
FI);
llvm::Function *Fn;
if (CXX20ModuleInits && getContext().getModuleForCodeGen()) {
SmallString<256> InitFnName;
llvm::raw_svector_ostream Out(InitFnName);
cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
.mangleModuleInitializer(getContext().getModuleForCodeGen(), Out);
Fn = CreateGlobalInitOrCleanUpFunction(
FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
llvm::GlobalVariable::ExternalLinkage);
} else
Fn = CreateGlobalInitOrCleanUpFunction(
FTy,
llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
FI);
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
AddGlobalCtor(Fn);
// In OpenCL global init functions must be converted to kernels in order to
@ -718,7 +887,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
Fn->addFnAttr("device-init");
}
CXXGlobalInits.clear();
ModuleInits.clear();
}
void CodeGenModule::EmitCXXGlobalCleanUpFunc() {

View File

@ -877,7 +877,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
/// Determine whether this expression refers to a flexible array member in a
/// struct. We disable array bounds checks for such members.
static bool isFlexibleArrayMemberExpr(const Expr *E) {
static bool isFlexibleArrayMemberExpr(const Expr *E,
unsigned StrictFlexArraysLevel) {
// For compatibility with existing code, we treat arrays of length 0 or
// 1 as flexible array members.
// FIXME: This is inconsistent with the warning code in SemaChecking. Unify
@ -886,6 +887,11 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
// FIXME: Sema doesn't treat [1] as a flexible array member if the bound
// was produced by macro expansion.
if (StrictFlexArraysLevel >= 2 && CAT->getSize().ugt(0))
return false;
// FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing
// arrays to be treated as flexible-array-members, we still emit ubsan
// checks as if they are not.
if (CAT->getSize().ugt(1))
return false;
} else if (!isa<IncompleteArrayType>(AT))
@ -900,8 +906,10 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
// FIXME: Sema doesn't treat a T[1] union member as a flexible array
// member, only a T[0] or T[] member gets that treatment.
// Under StrictFlexArraysLevel, obey c99+ that disallows FAM in union, see
// C11 6.7.2.1 §18
if (FD->getParent()->isUnion())
return true;
return StrictFlexArraysLevel < 2;
RecordDecl::field_iterator FI(
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
@ -954,8 +962,10 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
static llvm::Value *getArrayIndexingBound(
CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType) {
static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
const Expr *Base,
QualType &IndexedType,
unsigned StrictFlexArraysLevel) {
// For the vector indexing extension, the bound is the number of elements.
if (const VectorType *VT = Base->getType()->getAs<VectorType>()) {
IndexedType = Base->getType();
@ -966,7 +976,7 @@ static llvm::Value *getArrayIndexingBound(
if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
!isFlexibleArrayMemberExpr(CE->getSubExpr())) {
!isFlexibleArrayMemberExpr(CE->getSubExpr(), StrictFlexArraysLevel)) {
IndexedType = CE->getSubExpr()->getType();
const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe();
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
@ -993,8 +1003,11 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
"should not be called unless adding bounds checks");
SanitizerScope SanScope(this);
const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
QualType IndexedType;
llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType);
llvm::Value *Bound =
getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel);
if (!Bound)
return;

View File

@ -34,7 +34,8 @@ namespace llvm {
namespace clang {
namespace CodeGen {
class CodeGenFunction;
class CGFunctionInfo;
class CodeGenFunction;
}
class FieldDecl;

View File

@ -2603,14 +2603,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
for (const auto *E : GS->labels()) {
JumpDest Dest = getJumpDestForLabel(E->getLabel());
Transfer.push_back(Dest.getBlock());
llvm::BlockAddress *BA =
llvm::BlockAddress::get(CurFn, Dest.getBlock());
Args.push_back(BA);
ArgTypes.push_back(BA->getType());
ArgElemTypes.push_back(nullptr);
if (!Constraints.empty())
Constraints += ',';
Constraints += 'i';
Constraints += "!i";
}
Fallthrough = createBasicBlock("asm.fallthrough");
}

View File

@ -5203,8 +5203,30 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}
bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T) {
return T.clauses().empty();
}
void CodeGenFunction::EmitOMPTaskgroupDirective(
const OMPTaskgroupDirective &S) {
OMPLexicalScope Scope(*this, S, OMPD_unknown);
if (CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S)) {
llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
AllocaInsertPt->getIterator());
auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
InsertPointTy CodeGenIP) {
Builder.restoreIP(CodeGenIP);
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
if (!CapturedStmtInfo)
CapturedStmtInfo = &CapStmtInfo;
Builder.restoreIP(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
return;
}
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
if (const Expr *E = S.getReductionRef()) {
@ -5230,7 +5252,6 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
}
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
}

View File

@ -852,7 +852,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone)
if (CGM.isProfileInstrExcluded(Fn, Loc))
if (CGM.isFunctionBlockedFromProfileInstr(Fn, Loc))
Fn->addFnAttr(llvm::Attribute::NoProfile);
unsigned Count, Offset;

View File

@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
#include "ABIInfo.h"
#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
@ -32,7 +33,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
@ -58,6 +58,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CRC.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@ -136,6 +137,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
GlobalsInt8PtrTy = Int8Ty->getPointerTo(DL.getDefaultGlobalsAddressSpace());
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
// Build C++20 Module initializers.
// TODO: Add Microsoft here once we know the mangling required for the
// initializers.
CXX20ModuleInits =
LangOpts.CPlusPlusModules && getCXXABI().getMangleContext().getKind() ==
ItaniumMangleContext::MK_Itanium;
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
if (LangOpts.ObjC)
@ -510,6 +518,9 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
}
void CodeGenModule::Release() {
Module *Primary = getContext().getModuleForCodeGen();
if (CXX20ModuleInits && Primary && !Primary->isModuleMapModule())
EmitModuleInitializers(Primary);
EmitDeferred();
DeferredDecls.insert(EmittedDeferredDecls.begin(),
EmittedDeferredDecls.end());
@ -518,7 +529,10 @@ void CodeGenModule::Release() {
applyGlobalValReplacements();
applyReplacements();
emitMultiVersionFunctions();
EmitCXXGlobalInitFunc();
if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition())
EmitCXXModuleInitFunc(Primary);
else
EmitCXXGlobalInitFunc();
EmitCXXGlobalCleanUpFunc();
registerGlobalDtorsWithAtExit();
EmitCXXThreadLocalInitFunc();
@ -742,19 +756,22 @@ void CodeGenModule::Release() {
if (CodeGenOpts.CFProtectionReturn &&
Target.checkCFProtectionReturnSupported(getDiags())) {
// Indicate that we want to instrument return control flow protection.
getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return",
getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return",
1);
}
if (CodeGenOpts.CFProtectionBranch &&
Target.checkCFProtectionBranchSupported(getDiags())) {
// Indicate that we want to instrument branch control flow protection.
getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch",
getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
1);
}
if (CodeGenOpts.IBTSeal)
getModule().addModuleFlag(llvm::Module::Override, "ibt-seal", 1);
getModule().addModuleFlag(llvm::Module::Min, "ibt-seal", 1);
if (CodeGenOpts.FunctionReturnThunks)
getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1);
// Add module metadata for return address signing (ignoring
// non-leaf/all) and stack tagging. These are actually turned on by function
@ -2498,6 +2515,31 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
}
}
void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) {
// Emit the initializers in the order that sub-modules appear in the
// source, first Global Module Fragments, if present.
if (auto GMF = Primary->getGlobalModuleFragment()) {
for (Decl *D : getContext().getModuleInitializers(GMF)) {
assert(D->getKind() == Decl::Var && "GMF initializer decl is not a var?");
EmitTopLevelDecl(D);
}
}
// Second any associated with the module, itself.
for (Decl *D : getContext().getModuleInitializers(Primary)) {
// Skip import decls, the inits for those are called explicitly.
if (D->getKind() == Decl::Import)
continue;
EmitTopLevelDecl(D);
}
// Third any associated with the Privat eMOdule Fragment, if present.
if (auto PMF = Primary->getPrivateModuleFragment()) {
for (Decl *D : getContext().getModuleInitializers(PMF)) {
assert(D->getKind() == Decl::Var && "PMF initializer decl is not a var?");
EmitTopLevelDecl(D);
}
}
}
void CodeGenModule::EmitModuleLinkOptions() {
// Collect the set of all of the modules we want to visit to emit link
// options, which is essentially the imported modules and all of their
@ -2776,16 +2818,18 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
// NoSanitize by function name.
if (NoSanitizeL.containsFunction(Kind, Fn->getName()))
return true;
// NoSanitize by location.
// NoSanitize by location. Check "mainfile" prefix.
auto &SM = Context.getSourceManager();
const FileEntry &MainFile = *SM.getFileEntryForID(SM.getMainFileID());
if (NoSanitizeL.containsMainFile(Kind, MainFile.getName()))
return true;
// Check "src" prefix.
if (Loc.isValid())
return NoSanitizeL.containsLocation(Kind, Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
auto &SM = Context.getSourceManager();
if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
return NoSanitizeL.containsFile(Kind, MainFile->getName());
}
return false;
return NoSanitizeL.containsFile(Kind, MainFile.getName());
}
bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
@ -2795,8 +2839,13 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
const auto &NoSanitizeL = getContext().getNoSanitizeList();
if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category))
return true;
auto &SM = Context.getSourceManager();
if (NoSanitizeL.containsMainFile(
Kind, SM.getFileEntryForID(SM.getMainFileID())->getName(), Category))
return true;
if (NoSanitizeL.containsLocation(Kind, Loc, Category))
return true;
// Check global type.
if (!Ty.isNull()) {
// Drill down the array types: if global variable of a fixed type is
@ -2840,8 +2889,8 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
return true;
}
bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
SourceLocation Loc) const {
bool CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn,
SourceLocation Loc) const {
const auto &ProfileList = getContext().getProfileList();
// If the profile list is empty, then instrument everything.
if (ProfileList.isEmpty())
@ -2868,6 +2917,20 @@ bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
return ProfileList.getDefault();
}
bool CodeGenModule::isFunctionBlockedFromProfileInstr(
llvm::Function *Fn, SourceLocation Loc) const {
if (isFunctionBlockedByProfileList(Fn, Loc))
return true;
auto NumGroups = getCodeGenOpts().ProfileTotalFunctionGroups;
if (NumGroups > 1) {
auto Group = llvm::crc32(arrayRefFromStringRef(Fn->getName())) % NumGroups;
if (Group != getCodeGenOpts().ProfileSelectedFunctionGroup)
return true;
}
return false;
}
bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified.
if (LangOpts.EmitAllDecls)
@ -2903,12 +2966,20 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// explicitly instantiated, so they should not be emitted eagerly.
return false;
}
if (const auto *VD = dyn_cast<VarDecl>(Global))
if (const auto *VD = dyn_cast<VarDecl>(Global)) {
if (Context.getInlineVariableDefinitionKind(VD) ==
ASTContext::InlineVariableDefinitionKind::WeakUnknown)
// A definition of an inline constexpr static data member may change
// linkage later if it's redeclared outside the class.
return false;
if (CXX20ModuleInits && VD->getOwningModule() &&
!VD->getOwningModule()->isModuleMapModule()) {
// For CXX20, module-owned initializers need to be deferred, since it is
// not known at this point if they will be run for the current module or
// as part of the initializer for an imported one.
return false;
}
}
// If OpenMP is enabled and threadprivates must be generated like TLS, delay
// codegen for global variables, because they may be marked as threadprivate.
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
@ -6208,6 +6279,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitImportDecl(*Import);
}
// For C++ standard modules we are done - we will call the module
// initializer for imported modules, and that will likewise call those for
// any imports it has.
if (CXX20ModuleInits && Import->getImportedOwningModule() &&
!Import->getImportedOwningModule()->isModuleMapModule())
break;
// For clang C++ module map modules the initializers for sub-modules are
// emitted here.
// Find all of the submodules and emit the module initializers.
llvm::SmallPtrSet<clang::Module *, 16> Visited;
SmallVector<clang::Module *, 16> Stack;
@ -6892,3 +6973,31 @@ void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
OS << getContext().getCUIDHash();
}
}
void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
assert(DeferredDeclsToEmit.empty() &&
"Should have emitted all decls deferred to emit.");
assert(NewBuilder->DeferredDecls.empty() &&
"Newly created module should not have deferred decls");
NewBuilder->DeferredDecls = std::move(DeferredDecls);
assert(NewBuilder->DeferredVTables.empty() &&
"Newly created module should not have deferred vtables");
NewBuilder->DeferredVTables = std::move(DeferredVTables);
assert(NewBuilder->MangledDeclNames.empty() &&
"Newly created module should not have mangled decl names");
assert(NewBuilder->Manglings.empty() &&
"Newly created module should not have manglings");
NewBuilder->Manglings = std::move(Manglings);
assert(WeakRefReferences.empty() && "Not all WeakRefRefs have been applied");
NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
NewBuilder->TBAA = std::move(TBAA);
assert(NewBuilder->EmittedDeferredDecls.empty() &&
"Still have (unmerged) EmittedDeferredDecls deferred decls");
NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
}

View File

@ -303,7 +303,7 @@ class CodeGenModule : public CodeGenTypeCache {
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
std::string ModuleNameHash;
bool CXX20ModuleInits = false;
std::unique_ptr<CodeGenTBAA> TBAA;
mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
@ -1340,9 +1340,15 @@ class CodeGenModule : public CodeGenTypeCache {
bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
StringRef Category = StringRef()) const;
/// Returns true if function at the given location should be excluded from
/// profile instrumentation.
bool isProfileInstrExcluded(llvm::Function *Fn, SourceLocation Loc) const;
/// \returns true if \p Fn at \p Loc should be excluded from profile
/// instrumentation by the SCL passed by \p -fprofile-list.
bool isFunctionBlockedByProfileList(llvm::Function *Fn,
SourceLocation Loc) const;
/// \returns true if \p Fn at \p Loc should be excluded from profile
/// instrumentation.
bool isFunctionBlockedFromProfileInstr(llvm::Function *Fn,
SourceLocation Loc) const;
SanitizerMetadata *getSanitizerMetadata() {
return SanitizerMD.get();
@ -1508,34 +1514,7 @@ class CodeGenModule : public CodeGenTypeCache {
/// Move some lazily-emitted states to the NewBuilder. This is especially
/// essential for the incremental parsing environment like Clang Interpreter,
/// because we'll lose all important information after each repl.
void moveLazyEmissionStates(CodeGenModule *NewBuilder) {
assert(DeferredDeclsToEmit.empty() &&
"Should have emitted all decls deferred to emit.");
assert(NewBuilder->DeferredDecls.empty() &&
"Newly created module should not have deferred decls");
NewBuilder->DeferredDecls = std::move(DeferredDecls);
assert(NewBuilder->DeferredVTables.empty() &&
"Newly created module should not have deferred vtables");
NewBuilder->DeferredVTables = std::move(DeferredVTables);
assert(NewBuilder->MangledDeclNames.empty() &&
"Newly created module should not have mangled decl names");
assert(NewBuilder->Manglings.empty() &&
"Newly created module should not have manglings");
NewBuilder->Manglings = std::move(Manglings);
assert(WeakRefReferences.empty() &&
"Not all WeakRefRefs have been applied");
NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
NewBuilder->TBAA = std::move(TBAA);
assert(NewBuilder->EmittedDeferredDecls.empty() &&
"Still have (unmerged) EmittedDeferredDecls deferred decls");
NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
}
void moveLazyEmissionStates(CodeGenModule *NewBuilder);
private:
llvm::Constant *GetOrCreateLLVMFunction(
@ -1593,6 +1572,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// Emit the function that initializes C++ thread_local variables.
void EmitCXXThreadLocalInitFunc();
/// Emit the function that initializes global variables for a C++ Module.
void EmitCXXModuleInitFunc(clang::Module *Primary);
/// Emit the function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
@ -1660,6 +1642,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// Emit the llvm.used and llvm.compiler.used metadata.
void emitLLVMUsed();
/// For C++20 Itanium ABI, emit the initializers for the module.
void EmitModuleInitializers(clang::Module *Primary);
/// Emit the link options introduced by imported modules.
void EmitModuleLinkOptions();

View File

@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Basic/TargetInfo.h"
#include "ABIInfo.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
using namespace CodeGen;

View File

@ -35,7 +35,7 @@
#include "llvm/IR/Type.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm> // std::sort
#include <algorithm>
using namespace clang;
using namespace CodeGen;
@ -443,6 +443,9 @@ static Address emitMergePHI(CodeGenFunction &CGF,
return Address(PHI, Addr1.getElementType(), Align);
}
TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
: Info(std::move(Info)) {}
TargetCodeGenInfo::~TargetCodeGenInfo() = default;
// If someone can figure out a general rule for this, that would be great.
@ -10446,6 +10449,15 @@ ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const {
LTy = llvm::PointerType::getWithSamePointeeType(PtrTy, GlobalAS);
return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
}
// Force copying aggregate type in kernel arguments by value when
// compiling CUDA targeting SPIR-V. This is required for the object
// copied to be valid on the device.
// This behavior follows the CUDA spec
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing,
// and matches the NVPTX implementation.
if (isAggregateTypeForABI(Ty))
return getNaturalAlignIndirect(Ty, /* byval */ true);
}
return classifyArgumentType(Ty);
}

View File

@ -43,10 +43,10 @@ class CGBlockInfo;
/// codegeneration issues, like target-specific attributes, builtins and so
/// on.
class TargetCodeGenInfo {
std::unique_ptr<ABIInfo> Info = nullptr;
std::unique_ptr<ABIInfo> Info;
public:
TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) : Info(std::move(Info)) {}
TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info);
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.

View File

@ -4432,6 +4432,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
types::ID InputType = Input.first;
const Arg *InputArg = Input.second;
// The toolchain can be active for unsupported file types.
if ((Kind == Action::OFK_Cuda && !types::isCuda(InputType)) ||
(Kind == Action::OFK_HIP && !types::isHIP(InputType)))
continue;
// Get the product of all bound architectures and toolchains.
SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
for (const ToolChain *TC : ToolChains)
@ -4473,6 +4478,15 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
}
}
// Compiling HIP in non-RDC mode requires linking each action individually.
for (Action *&A : DeviceActions) {
if (A->getType() != types::TY_Object || Kind != Action::OFK_HIP ||
Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
continue;
ActionList LinkerInput = {A};
A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);
}
auto TCAndArch = TCAndArchs.begin();
for (Action *A : DeviceActions) {
DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
@ -4486,15 +4500,27 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
if (offloadDeviceOnly())
return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);
if (OffloadActions.empty())
return HostAction;
OffloadAction::DeviceDependences DDep;
if (C.isOffloadingHostKind(Action::OFK_Cuda) &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) {
// If we are not in RDC-mode we just emit the final CUDA fatbinary for each
// translation unit without requiring any linking.
// If we are not in RDC-mode we just emit the final CUDA fatbinary for
// each translation unit without requiring any linking.
Action *FatbinAction =
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);
DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),
nullptr, Action::OFK_Cuda);
} else if (C.isOffloadingHostKind(Action::OFK_HIP) &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false)) {
// If we are not in RDC-mode we just emit the final HIP fatbinary for each
// translation unit, linking each input individually.
Action *FatbinAction =
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),
nullptr, Action::OFK_HIP);
} else {
// Package all the offloading actions into a single output that can be
// embedded in the host and linked.
@ -4503,6 +4529,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
nullptr, Action::OFK_None);
}
OffloadAction::HostDependence HDep(
*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/nullptr, isa<CompileJobAction>(HostAction) ? DDep : DDeps);
@ -6254,6 +6281,7 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
if (IsClCompatMode) {
// Include CL and Core options.
IncludedFlagsBitmask |= options::CLOption;
IncludedFlagsBitmask |= options::CLDXCOption;
IncludedFlagsBitmask |= options::CoreOption;
} else {
ExcludedFlagsBitmask |= options::CLOption;
@ -6261,10 +6289,14 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
if (IsDXCMode()) {
// Include DXC and Core options.
IncludedFlagsBitmask |= options::DXCOption;
IncludedFlagsBitmask |= options::CLDXCOption;
IncludedFlagsBitmask |= options::CoreOption;
} else {
ExcludedFlagsBitmask |= options::DXCOption;
}
if (!IsClCompatMode && !IsDXCMode())
ExcludedFlagsBitmask |= options::CLDXCOption;
return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
}

View File

@ -267,10 +267,9 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
}
// Sort multilibs by priority and select the one with the highest priority.
llvm::sort(Filtered.begin(), Filtered.end(),
[](const Multilib &a, const Multilib &b) -> bool {
return a.priority() > b.priority();
});
llvm::sort(Filtered, [](const Multilib &a, const Multilib &b) -> bool {
return a.priority() > b.priority();
});
if (Filtered[0].priority() > Filtered[1].priority()) {
M = Filtered[0];

View File

@ -1013,6 +1013,8 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -222,11 +222,13 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
const Driver &D = getDriver();
// Add the Clang builtin headers (<resource>/include).
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
path::append(P, "/include");
addSystemInclude(DriverArgs, CC1Args, P.str());
// Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers)
path::append(P, "include", "ppc_wrappers");
addSystemInclude(DriverArgs, CC1Args, P);
// Add the Clang builtin headers (<resource>/include)
addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
}
// Return if -nostdlibinc is specified as a driver option.
@ -275,6 +277,8 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
return;
}

View File

@ -71,7 +71,7 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
} else if (!Args.hasArg(options::OPT_r)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/lib/ld-ananas.so");

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "RISCV.h"
#include "../Clang.h"
#include "ToolChains/CommonArgs.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Driver/Driver.h"
@ -138,10 +139,17 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// FreeBSD local, because ld.lld doesn't support relaxations
// -mno-relax is default, unless -mrelax is specified.
if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) {
Features.push_back("+relax");
else
// -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
// into .debug_addr, which is currently not implemented.
Arg *A;
if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
<< A->getAsString(Args);
} else {
Features.push_back("-relax");
}
// GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
// specified.

View File

@ -276,6 +276,8 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -956,6 +956,27 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-update=atomic");
}
int FunctionGroups = 1;
int SelectedFunctionGroup = 0;
if (const auto *A = Args.getLastArg(options::OPT_fprofile_function_groups)) {
StringRef Val = A->getValue();
if (Val.getAsInteger(0, FunctionGroups) || FunctionGroups < 1)
D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
}
if (const auto *A =
Args.getLastArg(options::OPT_fprofile_selected_function_group)) {
StringRef Val = A->getValue();
if (Val.getAsInteger(0, SelectedFunctionGroup) ||
SelectedFunctionGroup < 0 || SelectedFunctionGroup >= FunctionGroups)
D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
}
if (FunctionGroups != 1)
CmdArgs.push_back(Args.MakeArgString("-fprofile-function-groups=" +
Twine(FunctionGroups)));
if (SelectedFunctionGroup != 0)
CmdArgs.push_back(Args.MakeArgString("-fprofile-selected-function-group=" +
Twine(SelectedFunctionGroup)));
// Leave -fprofile-dir= an unused argument unless .gcda emission is
// enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
// the flag used. There is no -fno-profile-dir, so the user has no
@ -1902,18 +1923,11 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
StringRef Name = A->getValue();
std::string TuneCPU;
if (Name == "native")
TuneCPU = std::string(llvm::sys::getHostCPUName());
CmdArgs.push_back("-tune-cpu");
if (strcmp(A->getValue(), "native") == 0)
CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
else
TuneCPU = std::string(Name);
if (!TuneCPU.empty()) {
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
CmdArgs.push_back(A->getValue());
}
AddUnalignedAccessWarning(CmdArgs);
@ -2167,18 +2181,11 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
std::string TuneCPU;
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
StringRef Name = A->getValue();
Name = llvm::RISCV::resolveTuneCPUAlias(Name, Triple.isArch64Bit());
TuneCPU = std::string(Name);
}
if (!TuneCPU.empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
StringRef Name =
llvm::RISCV::resolveTuneCPUAlias(A->getValue(), Triple.isArch64Bit());
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
CmdArgs.push_back(Name.data());
}
}
@ -2202,19 +2209,12 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
StringRef Name = A->getValue();
std::string TuneCPU;
if (Name == "native")
TuneCPU = std::string(llvm::sys::getHostCPUName());
if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
CmdArgs.push_back("-tune-cpu");
if (strcmp(A->getValue(), "native") == 0)
CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
else
TuneCPU = std::string(Name);
if (!TuneCPU.empty()) {
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
CmdArgs.push_back(A->getValue());
}
bool HasBackchain =
@ -3490,6 +3490,7 @@ static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
types::ID InputType) {
const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version,
options::OPT_D,
options::OPT_I,
options::OPT_S,
options::OPT_emit_llvm,
options::OPT_disable_llvm_passes,
@ -3985,6 +3986,9 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
if (StringRef(A->getValue()) == "sarif" ||
StringRef(A->getValue()) == "SARIF")
D.Diag(diag::warn_drv_sarif_format_unstable);
}
if (const Arg *A = Args.getLastArg(
@ -4030,9 +4034,7 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
options::OPT_fno_spell_checking);
}
enum class DwarfFissionKind { None, Split, Single };
static DwarfFissionKind getDebugFissionKind(const Driver &D,
DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
const ArgList &Args, Arg *&Arg) {
Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
options::OPT_gno_split_dwarf);
@ -5388,9 +5390,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
// FIXME: Handle -mtune=.
(void)Args.hasArg(options::OPT_mtune_EQ);
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
StringRef CM = A->getValue();
if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
@ -5837,12 +5836,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
if (Args.hasArg(options::OPT_funstable)) {
CmdArgs.push_back("-funstable");
if (!Args.hasArg(options::OPT_fno_coroutines_ts))
CmdArgs.push_back("-fcoroutines-ts");
CmdArgs.push_back("-fmodules-ts");
}
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
CmdArgs.push_back("-fexperimental-new-constant-interpreter");
@ -6209,6 +6203,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftime_report_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_malign_double);
Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
@ -6243,6 +6238,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
options::OPT_fno_unroll_loops);
Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ);
Args.AddLastArg(CmdArgs, options::OPT_pthread);
if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
@ -6986,7 +6983,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(CudaDeviceInput->getFilename());
} else if (!HostOffloadingInputs.empty()) {
if (IsCuda && !IsRDCMode) {
if ((IsCuda || IsHIP) && !IsRDCMode) {
assert(HostOffloadingInputs.size() == 1 && "Only one input expected");
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(HostOffloadingInputs.front().getFilename());
@ -8448,14 +8445,14 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
// Forward remarks passes to the LLVM backend in the wrapper.
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("--pass-remarks=") + A->getValue()));
CmdArgs.push_back(Args.MakeArgString(Twine("--offload-opt=-pass-remarks=") +
A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("--pass-remarks-missed=") + A->getValue()));
CmdArgs.push_back(Args.MakeArgString(
Twine("--offload-opt=-pass-remarks-missed=") + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("--pass-remarks-analysis=") + A->getValue()));
CmdArgs.push_back(Args.MakeArgString(
Twine("--offload-opt=-pass-remarks-analysis=") + A->getValue()));
if (Args.getLastArg(options::OPT_save_temps_EQ))
CmdArgs.push_back("--save-temps");

View File

@ -198,6 +198,12 @@ class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
const char *LinkingOutput) const override;
};
enum class DwarfFissionKind { None, Split, Single };
DwarfFissionKind getDebugFissionKind(const Driver &D,
const llvm::opt::ArgList &Args,
llvm::opt::Arg *&Arg);
} // end namespace tools
} // end namespace driver

View File

@ -117,6 +117,8 @@ void CloudABI::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}

View File

@ -273,8 +273,11 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
}
}
clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {

View File

@ -1141,25 +1141,38 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
SmallString<128> P(getDriver().ClangExecutable);
llvm::sys::path::remove_filename(P); // 'clang'
llvm::sys::path::remove_filename(P); // 'bin'
llvm::sys::path::append(P, "lib", "arc");
// 'libarclite' usually lives in the same toolchain as 'clang'. However, the
// Swift open source toolchains for macOS distribute Clang without libarclite.
// In that case, to allow the linker to find 'libarclite', we point to the
// 'libarclite' in the XcodeDefault toolchain instead.
if (getXcodeDeveloperPath(P).empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
if (!getVFS().exists(P)) {
auto updatePath = [&](const Arg *A) {
// Try to infer the path to 'libarclite' in the toolchain from the
// specified SDK path.
StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
if (!XcodePathForSDK.empty()) {
P = XcodePathForSDK;
llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr");
}
if (XcodePathForSDK.empty())
return false;
P = XcodePathForSDK;
llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
"lib", "arc");
return getVFS().exists(P);
};
bool updated = false;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
updated = updatePath(A);
if (!updated) {
if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
updatePath(A);
}
}
CmdArgs.push_back("-force_load");
llvm::sys::path::append(P, "lib", "arc", "libarclite_");
llvm::sys::path::append(P, "libarclite_");
// Mash in the platform.
if (isTargetWatchOSSimulator())
P += "watchsimulator";
@ -2448,6 +2461,7 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
break;
}
}
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
@ -2455,6 +2469,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -69,7 +69,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-Bshareable");
else {
else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
}

View File

@ -170,7 +170,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
} else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
@ -389,10 +389,10 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
// back to '/usr/lib' if it doesn't exist.
if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
Triple.isPPC32()) &&
D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o")))
getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32"));
else
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
@ -411,14 +411,14 @@ unsigned FreeBSD::GetDefaultDwarfVersion() const {
void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/v1");
concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void FreeBSD::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", "",
DriverArgs, CC1Args);
addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"),
"", "", DriverArgs, CC1Args);
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@ -430,6 +430,8 @@ void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -101,7 +101,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
if (!Args.hasArg(options::OPT_shared)) {
if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) {
std::string Dyld = D.DyldPrefix;
if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
@ -417,6 +417,8 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -614,6 +614,8 @@ void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
break;

View File

@ -112,6 +112,8 @@ void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
"Only -lc++ (aka libxx) is supported in this toolchain.");
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}

View File

@ -308,6 +308,8 @@ void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
// if the value is libc++, and emits an error for other values.
GetCXXStdlibType(Args);
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
}
void NaClToolChain::addLibCxxIncludePaths(

View File

@ -139,7 +139,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
} else if (!Args.hasArg(options::OPT_r)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld.elf_so");

View File

@ -147,7 +147,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Bdynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
} else {
} else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld.so");
}
@ -284,7 +284,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
void OpenBSD::AddClangSystemIncludeArgs(
@ -317,13 +317,14 @@ void OpenBSD::AddClangSystemIncludeArgs(
return;
}
addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
addExternCSystemInclude(DriverArgs, CC1Args,
concat(D.SysRoot, "/usr/include"));
}
void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/v1");
concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@ -331,6 +332,8 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
bool Profiling = Args.hasArg(options::OPT_pg);
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread");
}

View File

@ -141,6 +141,8 @@ void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
tools::addArchSpecificRPath(*this, Args, CmdArgs);
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
// libc++ requires -lpthread under glibc environment

View File

@ -444,6 +444,8 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:

View File

@ -303,6 +303,7 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
// Skip templated functions.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
break;
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:

Some files were not shown because too many files have changed in this diff Show More