diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-27 20:11:54 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-04-09 14:54:48 +0000 |
commit | 74093eb27f687d9f89d8db457e410aec1cd71b6b (patch) | |
tree | fcd16e7627ee72b42c8dc9044d09c65fd7885a8e /contrib/llvm-project/clang | |
parent | 13a2180118bde2302097a9e6cc995c1b255724bb (diff) | |
download | src-74093eb27f687d9f89d8db457e410aec1cd71b6b.tar.gz src-74093eb27f687d9f89d8db457e410aec1cd71b6b.zip |
Merge llvm-project main llvmorg-15-init-17826-g1f8ae9d7e7e4
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-15-init-17826-g1f8ae9d7e7e4, the last commit before
the upstream release/16.x branch was created.
PR: 265425
MFC after: 2 weeks
(cherry picked from commit 972a253a57b6f144b0e4a3e2080a2a0076ec55a0)
Diffstat (limited to 'contrib/llvm-project/clang')
107 files changed, 2803 insertions, 1087 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Analysis/CFG.h b/contrib/llvm-project/clang/include/clang/Analysis/CFG.h index d8e7e1e43d81..4f16a6361950 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/CFG.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/CFG.h @@ -202,7 +202,8 @@ public: isa<ReturnedValueConstructionContext>(C) || isa<VariableConstructionContext>(C) || isa<ConstructorInitializerConstructionContext>(C) || - isa<ArgumentConstructionContext>(C))); + isa<ArgumentConstructionContext>(C) || + isa<LambdaCaptureConstructionContext>(C))); Data2.setPointer(const_cast<ConstructionContext *>(C)); } diff --git a/contrib/llvm-project/clang/include/clang/Analysis/ConstructionContext.h b/contrib/llvm-project/clang/include/clang/Analysis/ConstructionContext.h index a437160e0778..67a091199b91 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/ConstructionContext.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/ConstructionContext.h @@ -36,13 +36,14 @@ public: ElidedDestructorKind, ElidableConstructorKind, ArgumentKind, - STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind, - STATEMENT_WITH_INDEX_KIND_END=ArgumentKind, + LambdaCaptureKind, + STATEMENT_WITH_INDEX_KIND_BEGIN = ArgumentKind, + STATEMENT_WITH_INDEX_KIND_END = LambdaCaptureKind, STATEMENT_KIND_BEGIN = VariableKind, - STATEMENT_KIND_END = ArgumentKind, + STATEMENT_KIND_END = LambdaCaptureKind, InitializerKind, - INITIALIZER_KIND_BEGIN=InitializerKind, - INITIALIZER_KIND_END=InitializerKind + INITIALIZER_KIND_BEGIN = InitializerKind, + INITIALIZER_KIND_END = InitializerKind }; LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) { @@ -55,6 +56,8 @@ public: case ElidedDestructorKind: return "elide destructor"; case ElidableConstructorKind: return "elide constructor"; case ArgumentKind: return "construct into argument"; + case LambdaCaptureKind: + return "construct into lambda captured variable"; case InitializerKind: return "construct into member variable"; }; llvm_unreachable("Unknown ItemKind"); @@ -72,7 +75,7 @@ private: bool hasIndex() const { return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN && - Kind >= STATEMENT_WITH_INDEX_KIND_END; + Kind <= STATEMENT_WITH_INDEX_KIND_END; } bool hasInitializer() const { @@ -127,6 +130,9 @@ public: ConstructionContextItem(const CXXCtorInitializer *Init) : Data(Init), Kind(InitializerKind), Index(0) {} + ConstructionContextItem(const LambdaExpr *LE, unsigned Index) + : Data(LE), Kind(LambdaCaptureKind), Index(Index) {} + ItemKind getKind() const { return Kind; } LLVM_DUMP_METHOD StringRef getKindAsString() const { @@ -254,7 +260,8 @@ public: CXX17ElidedCopyReturnedValueKind, RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind, - ArgumentKind + ArgumentKind, + LambdaCaptureKind }; protected: @@ -298,6 +305,11 @@ public: const ConstructionContextLayer *TopLayer); Kind getKind() const { return K; } + + virtual const ArrayInitLoopExpr *getArrayInitLoop() const { return nullptr; } + + // Only declared to silence -Wnon-virtual-dtor warnings. + virtual ~ConstructionContext() = default; }; /// An abstract base class for local variable constructors. @@ -314,6 +326,12 @@ protected: public: const DeclStmt *getDeclStmt() const { return DS; } + const ArrayInitLoopExpr *getArrayInitLoop() const override { + const auto *Var = cast<VarDecl>(DS->getSingleDecl()); + + return dyn_cast<ArrayInitLoopExpr>(Var->getInit()); + } + static bool classof(const ConstructionContext *CC) { return CC->getKind() >= VARIABLE_BEGIN && CC->getKind() <= VARIABLE_END; @@ -381,6 +399,10 @@ protected: public: const CXXCtorInitializer *getCXXCtorInitializer() const { return I; } + const ArrayInitLoopExpr *getArrayInitLoop() const override { + return dyn_cast<ArrayInitLoopExpr>(I->getInit()); + } + static bool classof(const ConstructionContext *CC) { return CC->getKind() >= INITIALIZER_BEGIN && CC->getKind() <= INITIALIZER_END; @@ -659,6 +681,42 @@ public: } }; +class LambdaCaptureConstructionContext : public ConstructionContext { + // The lambda of which the initializer we capture. + const LambdaExpr *LE; + + // Index of the captured element in the captured list. + unsigned Index; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit LambdaCaptureConstructionContext(const LambdaExpr *LE, + unsigned Index) + : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {} + +public: + const LambdaExpr *getLambdaExpr() const { return LE; } + unsigned getIndex() const { return Index; } + + const Expr *getInitializer() const { + return *(LE->capture_init_begin() + Index); + } + + const FieldDecl *getFieldDecl() const { + auto It = LE->getLambdaClass()->field_begin(); + std::advance(It, Index); + return *It; + } + + const ArrayInitLoopExpr *getArrayInitLoop() const override { + return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer()); + } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == LambdaCaptureKind; + } +}; + } // end namespace clang #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h index abc3183e1b0b..b3e725ad3f6a 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -340,6 +340,10 @@ private: llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, DisjunctionValue *> DisjunctionVals; llvm::DenseMap<BoolValue *, NegationValue *> NegationVals; + llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ImplicationValue *> + ImplicationVals; + llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, BiconditionalValue *> + BiconditionalVals; // Flow conditions are tracked symbolically: each unique flow condition is // associated with a fresh symbolic variable (token), bound to the clause that diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index f17df36f6a4a..2e9c088d0e5c 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -128,6 +128,21 @@ public: /// with a symbolic representation of the `this` pointee. Environment(DataflowAnalysisContext &DACtx, const DeclContext &DeclCtx); + /// Creates and returns an environment to use for an inline analysis of the + /// callee. Uses the storage location from each argument in the `Call` as the + /// storage location for the corresponding parameter in the callee. + /// + /// Requirements: + /// + /// The callee of `Call` must be a `FunctionDecl` with a body. + /// + /// The body of the callee must not reference globals. + /// + /// The arguments of `Call` must map 1:1 to the callee's parameters. + /// + /// Each argument of `Call` must already have a `StorageLocation`. + Environment pushCall(const CallExpr *Call) const; + /// Returns true if and only if the environment is equivalent to `Other`, i.e /// the two environments: /// - have the same mappings from declarations to storage locations, diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MapLattice.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MapLattice.h index 014cd60841ee..16b0c978779a 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MapLattice.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/MapLattice.h @@ -54,10 +54,13 @@ public: // The `bottom` element is the empty map. static MapLattice bottom() { return MapLattice(); } - void insert(const std::pair<const key_type, mapped_type> &P) { C.insert(P); } + std::pair<iterator, bool> + insert(const std::pair<const key_type, mapped_type> &P) { + return C.insert(P); + } - void insert(std::pair<const key_type, mapped_type> &&P) { - C.insert(std::move(P)); + std::pair<iterator, bool> insert(std::pair<const key_type, mapped_type> &&P) { + return C.insert(std::move(P)); } unsigned size() const { return C.size(); } diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h index 25afa01f307c..cbb625487c1e 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -20,6 +20,12 @@ namespace clang { namespace dataflow { +struct TransferOptions { + /// Determines whether to analyze function bodies when present in the + /// translation unit. + bool ContextSensitive = false; +}; + /// Maps statements to the environments of basic blocks that contain them. class StmtToEnvMap { public: @@ -36,7 +42,8 @@ public: /// Requirements: /// /// `S` must not be `ParenExpr` or `ExprWithCleanups`. -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + TransferOptions Options); } // namespace dataflow } // namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h index b043062459e4..92700f164e7b 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h @@ -23,6 +23,7 @@ #include "clang/Analysis/FlowSensitive/ControlFlowContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" +#include "clang/Analysis/FlowSensitive/Transfer.h" #include "llvm/ADT/Any.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Error.h" @@ -36,6 +37,9 @@ struct DataflowAnalysisOptions { // (at which point the built-in transfer functions can be simply a standalone // analysis). bool ApplyBuiltinTransfer = true; + + /// Only has an effect if `ApplyBuiltinTransfer` is true. + TransferOptions BuiltinTransferOptions; }; /// Type-erased lattice element container. @@ -57,7 +61,7 @@ public: /// Deprecated. Use the `DataflowAnalysisOptions` constructor instead. TypeErasedDataflowAnalysis(bool ApplyBuiltinTransfer) - : Options({ApplyBuiltinTransfer}) {} + : Options({ApplyBuiltinTransfer, TransferOptions{}}) {} TypeErasedDataflowAnalysis(DataflowAnalysisOptions Options) : Options(Options) {} @@ -90,6 +94,11 @@ public: /// Determines whether to apply the built-in transfer functions, which model /// the heap and stack in the `Environment`. bool applyBuiltinTransfer() const { return Options.ApplyBuiltinTransfer; } + + /// Returns the options to be passed to the built-in transfer functions. + TransferOptions builtinTransferOptions() const { + return Options.BuiltinTransferOptions; + } }; /// Type-erased model of the program at a given program point. diff --git a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h index 70348f874543..c63799fe6a46 100644 --- a/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h +++ b/contrib/llvm-project/clang/include/clang/Analysis/FlowSensitive/Value.h @@ -37,12 +37,13 @@ public: Pointer, Struct, - // Synthetic boolean values are either atomic values or composites that - // represent conjunctions, disjunctions, and negations. + // Synthetic boolean values are either atomic values or logical connectives. AtomicBool, Conjunction, Disjunction, - Negation + Negation, + Implication, + Biconditional, }; explicit Value(Kind ValKind) : ValKind(ValKind) {} @@ -84,7 +85,9 @@ public: return Val->getKind() == Kind::AtomicBool || Val->getKind() == Kind::Conjunction || Val->getKind() == Kind::Disjunction || - Val->getKind() == Kind::Negation; + Val->getKind() == Kind::Negation || + Val->getKind() == Kind::Implication || + Val->getKind() == Kind::Biconditional; } }; @@ -162,6 +165,54 @@ private: BoolValue &SubVal; }; +/// Models a boolean implication. +/// +/// Equivalent to `!LHS v RHS`. +class ImplicationValue : public BoolValue { +public: + explicit ImplicationValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) + : BoolValue(Kind::Implication), LeftSubVal(LeftSubVal), + RightSubVal(RightSubVal) {} + + static bool classof(const Value *Val) { + return Val->getKind() == Kind::Implication; + } + + /// Returns the left sub-value of the implication. + BoolValue &getLeftSubValue() const { return LeftSubVal; } + + /// Returns the right sub-value of the implication. + BoolValue &getRightSubValue() const { return RightSubVal; } + +private: + BoolValue &LeftSubVal; + BoolValue &RightSubVal; +}; + +/// Models a boolean biconditional. +/// +/// Equivalent to `(LHS ^ RHS) v (!LHS ^ !RHS)`. +class BiconditionalValue : public BoolValue { +public: + explicit BiconditionalValue(BoolValue &LeftSubVal, BoolValue &RightSubVal) + : BoolValue(Kind::Biconditional), LeftSubVal(LeftSubVal), + RightSubVal(RightSubVal) {} + + static bool classof(const Value *Val) { + return Val->getKind() == Kind::Biconditional; + } + + /// Returns the left sub-value of the biconditional. + BoolValue &getLeftSubValue() const { return LeftSubVal; } + + /// Returns the right sub-value of the biconditional. + BoolValue &getRightSubValue() const { return RightSubVal; } + +private: + BoolValue &LeftSubVal; + BoolValue &RightSubVal; +}; + /// Models an integer. class IntegerValue : public Value { public: diff --git a/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td index aff0dbbdd94d..5c84e2fc5b77 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td +++ b/contrib/llvm-project/clang/include/clang/Basic/AttrDocs.td @@ -5040,6 +5040,12 @@ general this requires the template to be declared at least twice. For example: clang::preferred_name(wstring)]] basic_string { // ... }; + + +Note that the ``preferred_name`` attribute will be ignored when the compiler +writes a C++20 Module interface now. This is due to a compiler issue +(https://github.com/llvm/llvm-project/issues/56490) that blocks users to modularize +declarations with `preferred_name`. This is intended to be fixed in the future. }]; } diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h index 709d5e1dc80d..91b180f8004d 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticIDs.h @@ -45,18 +45,18 @@ namespace clang { // Start position for diagnostics. enum { DIAG_START_COMMON = 0, - DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, - DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, - DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, - DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, - DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, - DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE, - DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST, - DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_COMMENT, - DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_CROSSTU, - DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, - DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, - DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING + DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON), + DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER), + DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND), + DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION), + DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX), + DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE), + DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST), + DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT), + DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU), + DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA), + DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS), + DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING) }; class CustomDiagInfo; diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td index 352a050ba5cf..18adb21e2be0 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -282,7 +282,7 @@ def err_inline_nested_namespace_definition : Error< def err_expected_semi_after_attribute_list : Error< "expected ';' after attribute list">; def err_expected_semi_after_static_assert : Error< - "expected ';' after static_assert">; + "expected ';' after '%0'">; def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">; def err_single_decl_assign_in_for_range : Error< "range-based 'for' statement uses ':', not '='">; @@ -425,7 +425,7 @@ def err_unexpected_token_in_nested_name_spec : Error< def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; def warn_cxx98_compat_static_assert : Warning< - "static_assert declarations are incompatible with C++98">, + "'static_assert' declarations are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def ext_ms_static_assert : ExtWarn< "use of 'static_assert' without inclusion of <assert.h> is a Microsoft " @@ -538,6 +538,8 @@ def err_invalid_operator_on_type : Error< "cannot use %select{dot|arrow}0 operator on a type">; def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; +def err_while_loop_outside_of_a_function : Error< + "while loop outside of a function">; def err_brackets_go_after_unqualified_id : Error< "brackets are not allowed here; to declare an array, " "place the brackets after the %select{identifier|name}0">; diff --git a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td index 756102720049..6ff5b8de57fd 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm-project/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1526,12 +1526,12 @@ def err_messaging_class_with_direct_method : Error< // C++ declarations def err_static_assert_expression_is_not_constant : Error< - "static_assert expression is not an integral constant expression">; + "static assertion expression is not an integral constant expression">; def err_constexpr_if_condition_expression_is_not_constant : Error< "constexpr if condition is not a constant expression">; -def err_static_assert_failed : Error<"static_assert failed%select{: %1|}0">; +def err_static_assert_failed : Error<"static assertion failed%select{: %1|}0">; def err_static_assert_requirement_failed : Error< - "static_assert failed due to requirement '%0'%select{: %2|}1">; + "static assertion failed due to requirement '%0'%select{: %2|}1">; def warn_consteval_if_always_true : Warning< "consteval if is always true in an %select{unevaluated|immediate}0 context">, @@ -5774,6 +5774,8 @@ def warn_forward_class_redefinition : Warning< def err_redefinition_different_typedef : Error< "%select{typedef|type alias|type alias template}0 " "redefinition with different types%diff{ ($ vs $)|}1,2">; +def err_redefinition_different_concept : Error< + "redefinition of concept %0 with different template parameters or requirements">; def err_tag_reference_non_tag : Error< "%select{non-struct type|non-class type|non-union type|non-enum " "type|typedef|type alias|template|type alias template|template " diff --git a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def index 6fb31c5655ab..ad366821f3cb 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def +++ b/contrib/llvm-project/clang/include/clang/Basic/LangOptions.def @@ -195,6 +195,7 @@ VALUE_LANGOPT(DoubleSize , 32, 0, "width of double") VALUE_LANGOPT(LongDoubleSize , 32, 0, "width of long double") LANGOPT(PPCIEEELongDouble , 1, 0, "use IEEE 754 quadruple-precision for long double") LANGOPT(EnableAIXExtendedAltivecABI , 1, 0, "__EXTABI__ predefined macro") +LANGOPT(EnableAIXQuadwordAtomicsABI , 1, 0, "Use 16-byte atomic lock free semantics") COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") LANGOPT(ROPI , 1, 0, "Read-only position independence") diff --git a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def index 7b65a1537805..84fc0893c8b5 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def +++ b/contrib/llvm-project/clang/include/clang/Basic/TokenKinds.def @@ -908,6 +908,9 @@ PRAGMA_ANNOTATION(pragma_fp) // Annotation for the attribute pragma directives - #pragma clang attribute ... PRAGMA_ANNOTATION(pragma_attribute) +// Annotation for the riscv pragma directives - #pragma clang riscv intrinsic ... +PRAGMA_ANNOTATION(pragma_riscv) + // Annotations for module import translated from #include etc. ANNOTATION(module_include) ANNOTATION(module_begin) diff --git a/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td index d96020ee40d0..6b21f48110de 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td +++ b/contrib/llvm-project/clang/include/clang/Basic/riscv_vector.td @@ -186,7 +186,7 @@ class RVVBuiltin<string suffix, string prototype, string type_range, // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The // policy operand is located at the last position. - Policy MaskedPolicy = HasPolicyOperand; + Policy MaskedPolicyScheme = HasPolicyOperand; // The policy scheme for unmasked intrinsic IR. // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand. @@ -194,7 +194,7 @@ class RVVBuiltin<string suffix, string prototype, string type_range, // undef, tail policy is tail agnostic, otherwise policy is tail undisturbed. // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail // undisturbed. - Policy UnMaskedPolicy = NonePolicy; + Policy UnMaskedPolicyScheme = NonePolicy; // This builtin supports non-masked function overloading api. // All masked operations support overloading api. @@ -443,7 +443,7 @@ class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> { let HasMaskedOffOperand = false; } -let UnMaskedPolicy = HasPolicyOperand, +let UnMaskedPolicyScheme = HasPolicyOperand, HasMaskedOffOperand = false in { multiclass RVVSlideBuiltinSet { defm "" : RVVOutBuiltinSet<NAME, "csilxfd", @@ -582,7 +582,7 @@ class IsFloat<string type> { } let HasUnMaskedOverloaded = false, - MaskedPolicy = NonePolicy in { + MaskedPolicyScheme = NonePolicy in { class RVVVLEMaskBuiltin : RVVOutBuiltin<"m", "mPCUe", "c"> { let Name = "vlm_v"; let IRName = "vlm"; @@ -591,7 +591,7 @@ let HasUnMaskedOverloaded = false, } let HasUnMaskedOverloaded = false, - UnMaskedPolicy = HasPassthruOperand in { + UnMaskedPolicyScheme = HasPassthruOperand in { multiclass RVVVLEBuiltin<list<string> types> { let Name = NAME # "_v", IRName = "vle", @@ -664,7 +664,7 @@ multiclass RVVVLSEBuiltin<list<string> types> { IRName = "vlse", MaskedIRName ="vlse_mask", HasUnMaskedOverloaded = false, - UnMaskedPolicy = HasPassthruOperand in { + UnMaskedPolicyScheme = HasPassthruOperand in { foreach type = types in { def : RVVOutBuiltin<"v", "vPCet", type>; if !not(IsFloat<type>.val) then { @@ -675,7 +675,7 @@ multiclass RVVVLSEBuiltin<list<string> types> { } multiclass RVVIndexedLoad<string op> { - let UnMaskedPolicy = HasPassthruOperand in { + let UnMaskedPolicyScheme = HasPassthruOperand in { foreach type = TypeList in { foreach eew_list = EEWList[0-2] in { defvar eew = eew_list[0]; @@ -701,7 +701,7 @@ multiclass RVVIndexedLoad<string op> { } let HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl) std::swap(Ops[0], Ops[1]); @@ -738,7 +738,7 @@ multiclass RVVVSSEBuiltin<list<string> types> { IRName = "vsse", MaskedIRName = "vsse_mask", HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl) std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); @@ -762,7 +762,7 @@ multiclass RVVVSSEBuiltin<list<string> types> { multiclass RVVIndexedStore<string op> { let HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl) std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3); @@ -1141,7 +1141,7 @@ multiclass RVVUnitStridedSegStore<string op> { MaskedIRName = op # nf # "_mask", NF = nf, HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { // Builtin: (ptr, val0, val1, ..., vl) @@ -1187,7 +1187,7 @@ multiclass RVVStridedSegStore<string op> { MaskedIRName = op # nf # "_mask", NF = nf, HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { // Builtin: (ptr, stride, val0, val1, ..., vl). @@ -1229,7 +1229,7 @@ multiclass RVVIndexedSegStore<string op> { MaskedIRName = op # nf # "_mask", NF = nf, HasMaskedOffOperand = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { // Builtin: (ptr, index, val0, val1, ..., vl) @@ -1568,7 +1568,7 @@ def vsetvl_macro: RVVHeader; let HasBuiltinAlias = false, HasVL = false, HasMasked = false, - MaskedPolicy = NonePolicy, + MaskedPolicyScheme = NonePolicy, Log2LMUL = [0], ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type { @@ -1627,7 +1627,7 @@ defm : RVVIndexedSegStore<"vsoxseg">; // 12. Vector Integer Arithmetic Instructions // 12.1. Vector Single-Width Integer Add and Subtract -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vadd : RVVIntBinBuiltinSet; defm vsub : RVVIntBinBuiltinSet; defm vrsub : RVVOutOp1BuiltinSet<"vrsub", "csil", @@ -1638,7 +1638,7 @@ defm vneg_v : RVVPseudoUnaryBuiltin<"vrsub", "csil">; // 12.2. Vector Widening Integer Add/Subtract // Widening unsigned integer add/subtract, 2*SEW = SEW +/- SEW -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vwaddu : RVVUnsignedWidenBinBuiltinSet; defm vwsubu : RVVUnsignedWidenBinBuiltinSet; // Widening signed integer add/subtract, 2*SEW = SEW +/- SEW @@ -1657,7 +1657,7 @@ defm vwcvt_x_x_v : RVVPseudoVWCVTBuiltin<"vwadd", "vwcvt_x", "csi", [["w", "wv"]]>; // 12.3. Vector Integer Extension -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { def vsext_vf2 : RVVIntExt<"vsext", "w", "wv", "csi">; def vzext_vf2 : RVVIntExt<"vzext", "Uw", "UwUv", "csi">; @@ -1673,8 +1673,8 @@ let Log2LMUL = [-3, -2, -1, 0] in { } // 12.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions -let HasMasked = false, MaskedPolicy = NonePolicy in { - let UnMaskedPolicy = HasPassthruOperand in { +let HasMasked = false, MaskedPolicyScheme = NonePolicy in { + let UnMaskedPolicyScheme = HasPassthruOperand in { defm vadc : RVVCarryinBuiltinSet; defm vsbc : RVVCarryinBuiltinSet; } @@ -1685,7 +1685,7 @@ let HasMasked = false, MaskedPolicy = NonePolicy in { } // 12.5. Vector Bitwise Logical Instructions -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vand : RVVIntBinBuiltinSet; defm vxor : RVVIntBinBuiltinSet; defm vor : RVVIntBinBuiltinSet; @@ -1693,7 +1693,7 @@ defm vor : RVVIntBinBuiltinSet; defm vnot_v : RVVPseudoVNotBuiltin<"vxor", "csil">; // 12.6. Vector Single-Width Bit Shift Instructions -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vsll : RVVShiftBuiltinSet; defm vsrl : RVVUnsignedShiftBuiltinSet; defm vsra : RVVSignedShiftBuiltinSet; @@ -1707,7 +1707,7 @@ defm vncvt_x_x_w : RVVPseudoVNCVTBuiltin<"vnsrl", "vncvt_x", "csi", ["Uv", "UvUw"]]>; // 12.8. Vector Integer Comparison Instructions -let MaskedPolicy = NonePolicy in { +let MaskedPolicyScheme = NonePolicy in { defm vmseq : RVVIntMaskOutBuiltinSet; defm vmsne : RVVIntMaskOutBuiltinSet; defm vmsltu : RVVUnsignedMaskOutBuiltinSet; @@ -1721,7 +1721,7 @@ defm vmsge : RVVSignedMaskOutBuiltinSet; } // 12.9. Vector Integer Min/Max Instructions -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vminu : RVVUnsignedBinBuiltinSet; defm vmin : RVVSignedBinBuiltinSet; defm vmaxu : RVVUnsignedBinBuiltinSet; @@ -1745,7 +1745,7 @@ defm vrem : RVVSignedBinBuiltinSet; } // 12.12. Vector Widening Integer Multiply Instructions -let Log2LMUL = [-3, -2, -1, 0, 1, 2], UnMaskedPolicy = HasPassthruOperand in { +let Log2LMUL = [-3, -2, -1, 0, 1, 2], UnMaskedPolicyScheme = HasPassthruOperand in { defm vwmul : RVVOutOp0Op1BuiltinSet<"vwmul", "csi", [["vv", "w", "wvv"], ["vx", "w", "wve"]]>; @@ -1758,7 +1758,7 @@ defm vwmulsu : RVVOutOp0Op1BuiltinSet<"vwmulsu", "csi", } // 12.13. Vector Single-Width Integer Multiply-Add Instructions -let UnMaskedPolicy = HasPolicyOperand in { +let UnMaskedPolicyScheme = HasPolicyOperand in { defm vmacc : RVVIntTerBuiltinSet; defm vnmsac : RVVIntTerBuiltinSet; defm vmadd : RVVIntTerBuiltinSet; @@ -1783,7 +1783,7 @@ defm vwmaccus : RVVOutOp1Op2BuiltinSet<"vwmaccus", "csi", // 12.15. Vector Integer Merge Instructions // C/C++ Operand: (mask, op1, op2, vl), Intrinsic: (op1, op2, mask, vl) -let HasMasked = false, MaskedPolicy = NonePolicy, +let HasMasked = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()}; @@ -1798,7 +1798,9 @@ let HasMasked = false, MaskedPolicy = NonePolicy, } // 12.16. Vector Integer Move Instructions -let HasMasked = false, UnMaskedPolicy = HasPassthruOperand, MaskedPolicy = NonePolicy in { +let HasMasked = false, + UnMaskedPolicyScheme = HasPassthruOperand, + MaskedPolicyScheme = NonePolicy in { let OverloadedName = "vmv_v" in { defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csil", [["v", "Uv", "UvUv"]]>; @@ -1813,7 +1815,7 @@ let HasMasked = false, UnMaskedPolicy = HasPassthruOperand, MaskedPolicy = NoneP // 13. Vector Fixed-Point Arithmetic Instructions // 13.1. Vector Single-Width Saturating Add and Subtract -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vsaddu : RVVUnsignedBinBuiltinSet; defm vsadd : RVVSignedBinBuiltinSet; defm vssubu : RVVUnsignedBinBuiltinSet; @@ -1866,7 +1868,7 @@ let Log2LMUL = [-2, -1, 0, 1, 2] in { } // 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions -let UnMaskedPolicy = HasPolicyOperand in { +let UnMaskedPolicyScheme = HasPolicyOperand in { defm vfmacc : RVVFloatingTerBuiltinSet; defm vfnmacc : RVVFloatingTerBuiltinSet; defm vfmsac : RVVFloatingTerBuiltinSet; @@ -1884,7 +1886,7 @@ defm vfwnmsac : RVVFloatingWidenTerBuiltinSet; } // 14.8. Vector Floating-Point Square-Root Instruction -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { def vfsqrt : RVVFloatingUnaryVVBuiltin; // 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction @@ -1906,7 +1908,7 @@ defm vfneg_v : RVVPseudoVFUnaryBuiltin<"vfsgnjn", "xfd">; defm vfabs_v : RVVPseudoVFUnaryBuiltin<"vfsgnjx", "xfd">; // 14.13. Vector Floating-Point Compare Instructions -let MaskedPolicy = NonePolicy in { +let MaskedPolicyScheme = NonePolicy in { defm vmfeq : RVVFloatingMaskOutBuiltinSet; defm vmfne : RVVFloatingMaskOutBuiltinSet; defm vmflt : RVVFloatingMaskOutBuiltinSet; @@ -1916,12 +1918,12 @@ defm vmfge : RVVFloatingMaskOutBuiltinSet; } // 14.14. Vector Floating-Point Classify Instruction -let Name = "vfclass_v", UnMaskedPolicy = HasPassthruOperand in +let Name = "vfclass_v", UnMaskedPolicyScheme = HasPassthruOperand in def vfclass : RVVOp0Builtin<"Uv", "Uvv", "xfd">; // 14.15. Vector Floating-Point Merge Instructio // C/C++ Operand: (mask, op1, op2, vl), Builtin: (op1, op2, mask, vl) -let HasMasked = false, MaskedPolicy = NonePolicy, +let HasMasked = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()}; @@ -1935,13 +1937,13 @@ let HasMasked = false, MaskedPolicy = NonePolicy, } // 14.16. Vector Floating-Point Move Instruction -let HasMasked = false, UnMaskedPolicy = HasPassthruOperand, - HasUnMaskedOverloaded = false, MaskedPolicy = NonePolicy in +let HasMasked = false, UnMaskedPolicyScheme = HasPassthruOperand, + HasUnMaskedOverloaded = false, MaskedPolicyScheme = NonePolicy in defm vfmv_v : RVVOutBuiltinSet<"vfmv_v_f", "xfd", [["f", "v", "ve"]]>; // 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { def vfcvt_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_xu">; def vfcvt_x_f_v : RVVConvToSignedBuiltin<"vfcvt_x">; def vfcvt_rtz_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_rtz_xu">; @@ -1975,7 +1977,7 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in { // 15. Vector Reduction Operations // 15.1. Vector Single-Width Integer Reduction Instructions -let MaskedPolicy = NonePolicy in { +let MaskedPolicyScheme = NonePolicy in { defm vredsum : RVVIntReductionBuiltinSet; defm vredmaxu : RVVUnsignedReductionBuiltin; defm vredmax : RVVSignedReductionBuiltin; @@ -2021,7 +2023,7 @@ def vmset : RVVMaskNullaryBuiltin; defm vmmv_m : RVVPseudoMaskBuiltin<"vmand", "c">; defm vmnot_m : RVVPseudoMaskBuiltin<"vmnand", "c">; -let MaskedPolicy = NonePolicy in { +let MaskedPolicyScheme = NonePolicy in { // 16.2. Vector count population in mask vcpop.m def vcpop : RVVMaskOp0Builtin<"um">; @@ -2038,7 +2040,7 @@ def vmsif : RVVMaskUnaryBuiltin; def vmsof : RVVMaskUnaryBuiltin; } -let UnMaskedPolicy = HasPassthruOperand, HasUnMaskedOverloaded = false in { +let UnMaskedPolicyScheme = HasPassthruOperand, HasUnMaskedOverloaded = false in { // 16.8. Vector Iota Instruction defm viota : RVVOutBuiltinSet<"viota", "csil", [["m", "Uv", "Uvm"]]>; @@ -2049,7 +2051,7 @@ let UnMaskedPolicy = HasPassthruOperand, HasUnMaskedOverloaded = false in { // 17. Vector Permutation Instructions // 17.1. Integer Scalar Move Instructions -let HasMasked = false, MaskedPolicy = NonePolicy in { +let HasMasked = false, MaskedPolicyScheme = NonePolicy in { let HasVL = false, OverloadedName = "vmv_x" in defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil", [["s", "ve", "ev"], @@ -2061,7 +2063,7 @@ let HasMasked = false, MaskedPolicy = NonePolicy in { } // 17.2. Floating-Point Scalar Move Instructions -let HasMasked = false, MaskedPolicy = NonePolicy in { +let HasMasked = false, MaskedPolicyScheme = NonePolicy in { let HasVL = false, OverloadedName = "vfmv_f" in defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "xfd", [["s", "ve", "ev"]]>; @@ -2078,7 +2080,7 @@ defm vslideup : RVVSlideBuiltinSet; defm vslidedown : RVVSlideBuiltinSet; // 17.3.3. Vector Slide1up Instructions -let UnMaskedPolicy = HasPassthruOperand in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm vslide1up : RVVSlideOneBuiltinSet; defm vfslide1up : RVVFloatingBinVFBuiltinSet; @@ -2104,7 +2106,7 @@ defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csil", } // 17.5. Vector Compress Instruction -let HasMasked = false, MaskedPolicy = NonePolicy, +let HasMasked = false, MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3); IntrinsicTypes = {ResultType, Ops[3]->getType()}; @@ -2119,7 +2121,7 @@ let HasMasked = false, MaskedPolicy = NonePolicy, // Miscellaneous let HasMasked = false, HasVL = false, IRName = "" in { - let Name = "vreinterpret_v", MaskedPolicy = NonePolicy, + let Name = "vreinterpret_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ return Builder.CreateBitCast(Ops[0], ResultType); }] in { @@ -2141,7 +2143,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { } } - let Name = "vundefined", HasUnMaskedOverloaded = false, MaskedPolicy = NonePolicy, + let Name = "vundefined", HasUnMaskedOverloaded = false, + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ return llvm::UndefValue::get(ResultType); }] in { @@ -2151,7 +2154,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { // LMUL truncation // C/C++ Operand: VecTy, IR Operand: VecTy, Index - let Name = "vlmul_trunc_v", OverloadedName = "vlmul_trunc", MaskedPolicy = NonePolicy, + let Name = "vlmul_trunc_v", OverloadedName = "vlmul_trunc", + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { ID = Intrinsic::vector_extract; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -2169,7 +2173,8 @@ let HasMasked = false, HasVL = false, IRName = "" in { // LMUL extension // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index - let Name = "vlmul_ext_v", OverloadedName = "vlmul_ext", MaskedPolicy = NonePolicy, + let Name = "vlmul_ext_v", OverloadedName = "vlmul_ext", + MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ ID = Intrinsic::vector_insert; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -2187,7 +2192,7 @@ let HasMasked = false, HasVL = false, IRName = "" in { } } - let Name = "vget_v", MaskedPolicy = NonePolicy, + let Name = "vget_v", MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { ID = Intrinsic::vector_extract; @@ -2211,7 +2216,7 @@ let HasMasked = false, HasVL = false, IRName = "" in { } } - let Name = "vset_v", Log2LMUL = [0, 1, 2], MaskedPolicy = NonePolicy, + let Name = "vset_v", Log2LMUL = [0, 1, 2], MaskedPolicyScheme = NonePolicy, ManualCodegen = [{ { ID = Intrinsic::vector_insert; diff --git a/contrib/llvm-project/clang/include/clang/CodeGen/ModuleBuilder.h b/contrib/llvm-project/clang/include/clang/CodeGen/ModuleBuilder.h index 26587e73bf6c..edacd82bf899 100644 --- a/contrib/llvm-project/clang/include/clang/CodeGen/ModuleBuilder.h +++ b/contrib/llvm-project/clang/include/clang/CodeGen/ModuleBuilder.h @@ -14,12 +14,17 @@ #define LLVM_CLANG_CODEGEN_MODULEBUILDER_H #include "clang/AST/ASTConsumer.h" +#include "clang/Basic/LLVM.h" namespace llvm { class Constant; class LLVMContext; class Module; class StringRef; + + namespace vfs { + class FileSystem; + } } namespace clang { @@ -98,10 +103,11 @@ public: /// the allocated CodeGenerator instance. CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, - llvm::LLVMContext& C, + llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr); } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Driver/Driver.h b/contrib/llvm-project/clang/include/clang/Driver/Driver.h index 774eac613a10..0781d476ec4a 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Driver.h +++ b/contrib/llvm-project/clang/include/clang/Driver/Driver.h @@ -44,9 +44,7 @@ typedef SmallVector<InputInfo, 4> InputInfoList; class Command; class Compilation; -class JobList; class JobAction; -class SanitizerArgs; class ToolChain; /// Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options. diff --git a/contrib/llvm-project/clang/include/clang/Driver/Options.td b/contrib/llvm-project/clang/include/clang/Driver/Options.td index b9c2e4d528e4..3cab37b21aaf 100644 --- a/contrib/llvm-project/clang/include/clang/Driver/Options.td +++ b/contrib/llvm-project/clang/include/clang/Driver/Options.td @@ -3679,6 +3679,10 @@ def mabi_EQ_vec_extabi : Flag<["-"], "mabi=vec-extabi">, Group<m_Group>, Flags<[ MarshallingInfoFlag<LangOpts<"EnableAIXExtendedAltivecABI">>; def mabi_EQ_vec_default : Flag<["-"], "mabi=vec-default">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Enable the default Altivec ABI on AIX (AIX only). Uses only volatile vector registers.">; +def mabi_EQ_quadword_atomics : Flag<["-"], "mabi=quadword-atomics">, + Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Enable quadword atomics ABI on AIX (AIX PPC64 only). Uses lqarx/stqcx. instructions.">, + MarshallingInfoFlag<LangOpts<"EnableAIXQuadwordAtomicsABI">>; def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>; def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>; def msecure_plt : Flag<["-"], "msecure-plt">, Group<m_ppc_Features_Group>; diff --git a/contrib/llvm-project/clang/include/clang/Frontend/Utils.h b/contrib/llvm-project/clang/include/clang/Frontend/Utils.h index 240624d5408f..143cf4359f00 100644 --- a/contrib/llvm-project/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm-project/clang/include/clang/Frontend/Utils.h @@ -107,10 +107,10 @@ public: void finishedMainFile(DiagnosticsEngine &Diags) override; - bool needSystemDependencies() final override { return IncludeSystemHeaders; } + bool needSystemDependencies() final { return IncludeSystemHeaders; } bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, - bool IsModuleFile, bool IsMissing) final override; + bool IsModuleFile, bool IsMissing) final; protected: void outputDependencyFile(llvm::raw_ostream &OS); diff --git a/contrib/llvm-project/clang/include/clang/Lex/PreprocessingRecord.h b/contrib/llvm-project/clang/include/clang/Lex/PreprocessingRecord.h index 063929dd8f96..c97ca8628e14 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/PreprocessingRecord.h +++ b/contrib/llvm-project/clang/include/clang/Lex/PreprocessingRecord.h @@ -49,7 +49,6 @@ void operator delete(void *ptr, clang::PreprocessingRecord &PR, namespace clang { -class FileEntry; class IdentifierInfo; class MacroInfo; class SourceManager; diff --git a/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h index 8fc24c731035..79454b5addea 100644 --- a/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm-project/clang/include/clang/Lex/Preprocessor.h @@ -67,7 +67,6 @@ namespace clang { class CodeCompletionHandler; class CommentHandler; class DirectoryEntry; -class DirectoryLookup; class EmptylineHandler; class ExternalPreprocessorSource; class FileEntry; diff --git a/contrib/llvm-project/clang/include/clang/Parse/Parser.h b/contrib/llvm-project/clang/include/clang/Parse/Parser.h index 76e1c9db5284..41bfc9f48ecc 100644 --- a/contrib/llvm-project/clang/include/clang/Parse/Parser.h +++ b/contrib/llvm-project/clang/include/clang/Parse/Parser.h @@ -215,6 +215,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> AttributePragmaHandler; std::unique_ptr<PragmaHandler> MaxTokensHerePragmaHandler; std::unique_ptr<PragmaHandler> MaxTokensTotalPragmaHandler; + std::unique_ptr<PragmaHandler> RISCVPragmaHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -1043,7 +1044,7 @@ private: /// If the next token is not a semicolon, this emits the specified diagnostic, /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior /// to the semicolon, consumes that extra token. - bool ExpectAndConsumeSemi(unsigned DiagID); + bool ExpectAndConsumeSemi(unsigned DiagID , StringRef TokenUsed = ""); /// The kind of extra semi diagnostic to emit. enum ExtraSemiKind { diff --git a/contrib/llvm-project/clang/include/clang/Sema/Overload.h b/contrib/llvm-project/clang/include/clang/Sema/Overload.h index 48997e186ef6..fb4812675d9a 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Overload.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Overload.h @@ -795,6 +795,10 @@ class Sema; /// This candidate was not viable because its associated constraints were /// not satisfied. ovl_fail_constraints_not_satisfied, + + /// This candidate was not viable because it has internal linkage and is + /// from a different module unit than the use. + ovl_fail_module_mismatched, }; /// A list of implicit conversion sequences for the arguments of an diff --git a/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h b/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h new file mode 100644 index 000000000000..505100249d6f --- /dev/null +++ b/contrib/llvm-project/clang/include/clang/Sema/RISCVIntrinsicManager.h @@ -0,0 +1,36 @@ +//===- RISCVIntrinsicManager.h - RISC-V Intrinsic Handler -------*- 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 the RISCVIntrinsicManager, which handles RISC-V vector +// intrinsic functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H +#define LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H + +namespace clang { +class Sema; +class LookupResult; +class IdentifierInfo; +class Preprocessor; + +namespace sema { +class RISCVIntrinsicManager { +public: + virtual ~RISCVIntrinsicManager() = default; + + // Create RISC-V intrinsic and insert into symbol table and return true if + // found, otherwise return false. + virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, + Preprocessor &PP) = 0; +}; +} // end namespace sema +} // end namespace clang + +#endif diff --git a/contrib/llvm-project/clang/include/clang/Sema/Scope.h b/contrib/llvm-project/clang/include/clang/Sema/Scope.h index f4c50864f51c..3749d925b106 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Scope.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Scope.h @@ -210,9 +210,19 @@ private: /// Used to determine if errors occurred in this scope. DiagnosticErrorTrap ErrorTrap; - /// A lattice consisting of undefined, a single NRVO candidate variable in - /// this scope, or over-defined. The bit is true when over-defined. - llvm::PointerIntPair<VarDecl *, 1, bool> NRVO; + /// A single NRVO candidate variable in this scope. + /// There are three possible values: + /// 1) pointer to VarDecl that denotes NRVO candidate itself. + /// 2) nullptr value means that NRVO is not allowed in this scope + /// (e.g. return a function parameter). + /// 3) None value means that there is no NRVO candidate in this scope + /// (i.e. there are no return statements in this scope). + Optional<VarDecl *> NRVO; + + /// Represents return slots for NRVO candidates in the current scope. + /// If a variable is present in this set, it means that a return slot is + /// available for this variable in the current scope. + llvm::SmallPtrSet<VarDecl *, 8> ReturnSlots; void setFlags(Scope *Parent, unsigned F); @@ -304,6 +314,10 @@ public: bool decl_empty() const { return DeclsInScope.empty(); } void AddDecl(Decl *D) { + if (auto *VD = dyn_cast<VarDecl>(D)) + if (!isa<ParmVarDecl>(VD)) + ReturnSlots.insert(VD); + DeclsInScope.insert(D); } @@ -527,23 +541,9 @@ public: UsingDirectives.end()); } - void addNRVOCandidate(VarDecl *VD) { - if (NRVO.getInt()) - return; - if (NRVO.getPointer() == nullptr) { - NRVO.setPointer(VD); - return; - } - if (NRVO.getPointer() != VD) - setNoNRVO(); - } - - void setNoNRVO() { - NRVO.setInt(true); - NRVO.setPointer(nullptr); - } + void updateNRVOCandidate(VarDecl *VD); - void mergeNRVOIntoParent(); + void applyNRVO(); /// Init - This is used by the parser to implement scope caching. void Init(Scope *parent, unsigned flags); diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h index a33d85cc954d..06ea0b417cb3 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h @@ -226,6 +226,7 @@ namespace sema { class FunctionScopeInfo; class LambdaScopeInfo; class PossiblyUnreachableDiag; + class RISCVIntrinsicManager; class SemaPPCallbacks; class TemplateDeductionInfo; } @@ -1587,7 +1588,12 @@ public: /// assignment. llvm::DenseMap<const VarDecl *, int> RefsMinusAssignments; + /// Indicate RISC-V vector builtin functions enabled or not. + bool DeclareRISCVVBuiltins = false; + private: + std::unique_ptr<sema::RISCVIntrinsicManager> RVIntrinsicManager; + Optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo; bool WarnedDarwinSDKInfoMissing = false; @@ -8260,6 +8266,9 @@ public: Scope *S, MultiTemplateParamsArg TemplateParameterLists, IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr); + void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous, + bool &AddToScope); + RequiresExprBodyDecl * ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, ArrayRef<ParmVarDecl *> LocalParameters, @@ -12170,7 +12179,8 @@ public: // For simple assignment, pass both expressions and a null converted type. // For compound assignment, pass both expressions and the converted type. QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] - Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType); + Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType, + BinaryOperatorKind Opc); ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opcode, Expr *Op); @@ -13586,6 +13596,8 @@ void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation, llvm::StringRef StackSlotLabel, AlignPackInfo Value); +std::unique_ptr<sema::RISCVIntrinsicManager> +CreateRISCVIntrinsicManager(Sema &S); } // end namespace clang namespace llvm { diff --git a/contrib/llvm-project/clang/include/clang/Sema/Template.h b/contrib/llvm-project/clang/include/clang/Sema/Template.h index 5dcde77b5dd3..8df92b7000f3 100644 --- a/contrib/llvm-project/clang/include/clang/Sema/Template.h +++ b/contrib/llvm-project/clang/include/clang/Sema/Template.h @@ -75,6 +75,8 @@ enum class TemplateSubstitutionKind : char { class MultiLevelTemplateArgumentList { /// The template argument list at a certain template depth using ArgList = ArrayRef<TemplateArgument>; + using ArgListsIterator = SmallVector<ArgList, 4>::iterator; + using ConstArgListsIterator = SmallVector<ArgList, 4>::const_iterator; /// The template argument lists, stored from the innermost template /// argument list (first) to the outermost template argument list (last). @@ -121,6 +123,12 @@ enum class TemplateSubstitutionKind : char { return TemplateArgumentLists.size(); } + // Determine the number of substituted args at 'Depth'. + unsigned getNumSubsitutedArgs(unsigned Depth) const { + assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); + return TemplateArgumentLists[getNumLevels() - Depth - 1].size(); + } + unsigned getNumRetainedOuterLevels() const { return NumRetainedOuterLevels; } @@ -158,6 +166,14 @@ enum class TemplateSubstitutionKind : char { return !(*this)(Depth, Index).isNull(); } + bool isAnyArgInstantiationDependent() const { + for (ArgList List : TemplateArgumentLists) + for (const TemplateArgument &TA : List) + if (TA.isInstantiationDependent()) + return true; + return false; + } + /// Clear out a specific template argument. void setArgument(unsigned Depth, unsigned Index, TemplateArgument Arg) { @@ -183,6 +199,14 @@ enum class TemplateSubstitutionKind : char { TemplateArgumentLists.push_back(Args); } + /// Replaces the current 'innermost' level with the provided argument list. + /// This is useful for type deduction cases where we need to get the entire + /// list from the AST, but then add the deduced innermost list. + void replaceInnermostTemplateArguments(ArgList Args) { + assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); + TemplateArgumentLists[0] = Args; + } + /// Add an outermost level that we are not substituting. We have no /// arguments at this level, and do not remove it from the depth of inner /// template parameters that we instantiate. @@ -197,6 +221,16 @@ enum class TemplateSubstitutionKind : char { const ArgList &getInnermost() const { return TemplateArgumentLists.front(); } + /// Retrieve the outermost template argument list. + const ArgList &getOutermost() const { + return TemplateArgumentLists.back(); + } + ArgListsIterator begin() { return TemplateArgumentLists.begin(); } + ConstArgListsIterator begin() const { + return TemplateArgumentLists.begin(); + } + ArgListsIterator end() { return TemplateArgumentLists.end(); } + ConstArgListsIterator end() const { return TemplateArgumentLists.end(); } }; /// The context in which partial ordering of function templates occurs. diff --git a/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h index 6a3532d7272d..83bc7dcdfde3 100644 --- a/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm-project/clang/include/clang/Serialization/ASTWriter.h @@ -703,6 +703,10 @@ public: bool hasChain() const { return Chain; } ASTReader *getChain() const { return Chain; } + bool isWritingNamedModules() const { + return WritingModule && WritingModule->isModulePurview(); + } + private: // ASTDeserializationListener implementation void ReaderInitialized(ASTReader *Reader) override; diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 685dc66182ef..48da56c00f7a 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -731,7 +731,7 @@ public: PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BR, - PathSensitiveBugReport &R) override final; + PathSensitiveBugReport &R) final; }; } // namespace ento diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 116a5970c341..8773e171369f 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -622,6 +622,11 @@ public: getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx); + /// Retreives the size of the array in the pending ArrayInitLoopExpr. + static Optional<unsigned> getPendingInitLoop(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. @@ -816,7 +821,9 @@ private: /// Checks whether our policies allow us to inline a non-POD type array /// construction. - bool shouldInlineArrayConstruction(const ArrayType *Type); + bool shouldInlineArrayConstruction(const ProgramStateRef State, + const CXXConstructExpr *CE, + const LocationContext *LCtx); /// Checks whether we construct an array of non-POD type, and decides if the /// constructor should be inkoved once again. @@ -916,6 +923,16 @@ private: const CXXConstructExpr *E, const LocationContext *LCtx); + /// Sets the size of the array in a pending ArrayInitLoopExpr. + static ProgramStateRef setPendingInitLoop(ProgramStateRef State, + const CXXConstructExpr *E, + const LocationContext *LCtx, + unsigned Idx); + + static ProgramStateRef removePendingInitLoop(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 diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 1092d1292255..9927b6340793 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -55,8 +55,6 @@ template <typename T> struct ProgramStateTrait { } }; -class RangeSet; - /// \class ProgramState /// ProgramState - This class encapsulates: /// diff --git a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index c9c21fcf230e..2ae811ee3365 100644 --- a/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -40,7 +40,6 @@ class LabelDecl; namespace ento { -class BasicValueFactory; class CompoundValData; class LazyCompoundValData; class MemRegion; diff --git a/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h b/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h index a5e7e6d35cc8..7ee4896eea09 100644 --- a/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h +++ b/contrib/llvm-project/clang/include/clang/Support/RISCVVIntrinsicUtils.h @@ -18,6 +18,10 @@ #include <string> #include <vector> +namespace llvm { +class raw_ostream; +} // end namespace llvm + namespace clang { namespace RISCV { @@ -104,12 +108,14 @@ struct PrototypeDescriptor { uint8_t TM = static_cast<uint8_t>(TypeModifier::NoModifier); bool operator!=(const PrototypeDescriptor &PD) const { - return PD.PT != PT || PD.VTM != VTM || PD.TM != TM; + return !(*this == PD); } - bool operator>(const PrototypeDescriptor &PD) const { - return !(PD.PT <= PT && PD.VTM <= VTM && PD.TM <= TM); + bool operator==(const PrototypeDescriptor &PD) const { + return PD.PT == PT && PD.VTM == VTM && PD.TM == TM; + } + bool operator<(const PrototypeDescriptor &PD) const { + return std::tie(PT, VTM, TM) < std::tie(PD.PT, PD.VTM, PD.TM); } - static const PrototypeDescriptor Mask; static const PrototypeDescriptor Vector; static const PrototypeDescriptor VL; @@ -224,8 +230,12 @@ public: bool isFloat(unsigned Width) const { return isFloat() && ElementBitwidth == Width; } - + bool isConstant() const { return IsConstant; } bool isPointer() const { return IsPointer; } + unsigned getElementBitwidth() const { return ElementBitwidth; } + + ScalarTypeKind getScalarType() const { return ScalarType; } + VScaleVal getScale() const { return Scale; } private: // Verify RVV vector type and set Valid. @@ -263,18 +273,6 @@ public: PrototypeDescriptor Proto); }; -using RISCVPredefinedMacroT = uint8_t; - -enum RISCVPredefinedMacro : RISCVPredefinedMacroT { - Basic = 0, - V = 1 << 1, - Zvfh = 1 << 2, - RV64 = 1 << 3, - VectorMaxELen64 = 1 << 4, - VectorMaxELenFp32 = 1 << 5, - VectorMaxELenFp64 = 1 << 6, -}; - enum PolicyScheme : uint8_t { SchemeNone, HasPassthruOperand, @@ -302,7 +300,6 @@ private: // The types we use to obtain the specific LLVM intrinsic. They are index of // InputTypes. -1 means the return type. std::vector<int64_t> IntrinsicTypes; - RISCVPredefinedMacroT RISCVPredefinedMacros = 0; unsigned NF = 1; public: @@ -333,9 +330,6 @@ public: llvm::StringRef getIRName() const { return IRName; } llvm::StringRef getManualCodegen() const { return ManualCodegen; } PolicyScheme getPolicyScheme() const { return Scheme; } - RISCVPredefinedMacroT getRISCVPredefinedMacros() const { - return RISCVPredefinedMacros; - } unsigned getNF() const { return NF; } const std::vector<int64_t> &getIntrinsicTypes() const { return IntrinsicTypes; @@ -347,8 +341,72 @@ public: static std::string getSuffixStr(BasicType Type, int Log2LMUL, llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors); + + static llvm::SmallVector<PrototypeDescriptor> + computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype, + bool IsMasked, bool HasMaskedOffOperand, bool HasVL, + unsigned NF); +}; + +// RVVRequire should be sync'ed with target features, but only +// required features used in riscv_vector.td. +enum RVVRequire : uint8_t { + RVV_REQ_None = 0, + RVV_REQ_RV64 = 1 << 0, + RVV_REQ_FullMultiply = 1 << 1, + + LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_FullMultiply) +}; + +// Raw RVV intrinsic info, used to expand later. +// This struct is highly compact for minimized code size. +struct RVVIntrinsicRecord { + // Intrinsic name, e.g. vadd_vv + const char *Name; + + // Overloaded intrinsic name, could be empty if it can be computed from Name. + // e.g. vadd + const char *OverloadedName; + + // Prototype for this intrinsic, index of RVVSignatureTable. + uint16_t PrototypeIndex; + + // Suffix of intrinsic name, index of RVVSignatureTable. + uint16_t SuffixIndex; + + // Suffix of overloaded intrinsic name, index of RVVSignatureTable. + uint16_t OverloadedSuffixIndex; + + // Length of the prototype. + uint8_t PrototypeLength; + + // Length of intrinsic name suffix. + uint8_t SuffixLength; + + // Length of overloaded intrinsic suffix. + uint8_t OverloadedSuffixSize; + + // Required target features for this intrinsic. + uint8_t RequiredExtensions; + + // Supported type, mask of BasicType. + uint8_t TypeRangeMask; + + // Supported LMUL. + uint8_t Log2LMULMask; + + // Number of fields, greater than 1 if it's segment load/store. + uint8_t NF; + + bool HasMasked : 1; + bool HasVL : 1; + bool HasMaskedOffOperand : 1; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const RVVIntrinsicRecord &RVVInstrRecord); + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); } // end namespace RISCV } // end namespace clang diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h index 49e4a0c149f1..1a318da3acca 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h @@ -98,7 +98,7 @@ public: OptionRequirement() : Opt(createRefactoringOption<OptionType>()) {} ArrayRef<std::shared_ptr<RefactoringOption>> - getRefactoringOptions() const final override { + getRefactoringOptions() const final { return Opt; } diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h index 86fcc6ad0a79..5cb051d53433 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringActionRules.h @@ -52,7 +52,7 @@ using RefactoringActionRules = class SourceChangeRefactoringRule : public RefactoringActionRuleBase { public: void invoke(RefactoringResultConsumer &Consumer, - RefactoringRuleContext &Context) final override { + RefactoringRuleContext &Context) final { Expected<AtomicChanges> Changes = createSourceReplacements(Context); if (!Changes) Consumer.handleError(Changes.takeError()); @@ -74,7 +74,7 @@ private: class FindSymbolOccurrencesRefactoringRule : public RefactoringActionRuleBase { public: void invoke(RefactoringResultConsumer &Consumer, - RefactoringRuleContext &Context) final override { + RefactoringRuleContext &Context) final { Expected<SymbolOccurrences> Occurrences = findSymbolOccurrences(Context); if (!Occurrences) Consumer.handleError(Occurrences.takeError()); diff --git a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h index 1575a136b11c..75bd91d15016 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/Refactoring/RefactoringOptions.h @@ -24,7 +24,7 @@ template <typename T, typename = std::enable_if_t<traits::IsValidOptionType<T>::value>> class OptionalRefactoringOption : public RefactoringOption { public: - void passToVisitor(RefactoringOptionVisitor &Visitor) final override { + void passToVisitor(RefactoringOptionVisitor &Visitor) final { Visitor.visit(*this, Value); } @@ -48,7 +48,7 @@ public: const ValueType &getValue() const { return *OptionalRefactoringOption<T>::Value; } - bool isRequired() const final override { return true; } + bool isRequired() const final { return true; } }; } // end namespace tooling diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp index f7e7b73d1218..0273e5068371 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTImporter.h" -#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTImporterSharedState.h" #include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -34,6 +34,7 @@ #include "clang/AST/LambdaCapture.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" +#include "clang/AST/ParentMapContext.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" @@ -58,8 +59,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -3219,9 +3220,12 @@ Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, } // Returns true if the given D has a DeclContext up to the TranslationUnitDecl -// which is equal to the given DC. +// which is equal to the given DC, or D is equal to DC. static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { - const DeclContext *DCi = D->getDeclContext(); + const DeclContext *DCi = dyn_cast<DeclContext>(D); + if (!DCi) + DCi = D->getDeclContext(); + assert(DCi && "Declaration should have a context"); while (DCi != D->getTranslationUnitDecl()) { if (DCi == DC) return true; @@ -3230,9 +3234,36 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Decl *D) { return false; } +// Returns true if the statement S has a parent declaration that has a +// DeclContext that is inside (or equal to) DC. In a specific use case if DC is +// a FunctionDecl, check if statement S resides in the body of the function. +static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) { + ParentMapContext &ParentC = DC->getParentASTContext().getParentMapContext(); + DynTypedNodeList Parents = ParentC.getParents(*S); + while (!Parents.empty()) { + if (const Decl *PD = Parents.begin()->get<Decl>()) + return isAncestorDeclContextOf(DC, PD); + Parents = ParentC.getParents(*Parents.begin()); + } + return false; +} + static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) { if (T.isNull()) return false; + + auto CheckTemplateArgument = [FD](const TemplateArgument &Arg) { + switch (Arg.getKind()) { + case TemplateArgument::Type: + return hasTypeDeclaredInsideFunction(Arg.getAsType(), FD); + case TemplateArgument::Expression: + return isAncestorDeclContextOf(FD, Arg.getAsExpr()); + default: + // FIXME: Handle other argument kinds. + return false; + } + }; + if (const auto *RecordT = T->getAs<RecordType>()) { const RecordDecl *RD = RecordT->getDecl(); assert(RD); @@ -3241,12 +3272,15 @@ static bool hasTypeDeclaredInsideFunction(QualType T, const FunctionDecl *FD) { return true; } if (const auto *RDTempl = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - return llvm::count_if(RDTempl->getTemplateArgs().asArray(), - [FD](const TemplateArgument &Arg) { - return hasTypeDeclaredInsideFunction( - Arg.getAsType(), FD); - }); + if (llvm::count_if(RDTempl->getTemplateArgs().asArray(), + CheckTemplateArgument)) + return true; + // Note: It is possible that T can be get as both a RecordType and a + // TemplateSpecializationType. } + if (const auto *TST = T->getAs<TemplateSpecializationType>()) + return llvm::count_if(TST->template_arguments(), CheckTemplateArgument); + return false; } diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp index 8580cc639d2d..2f3fd34d511c 100644 --- a/contrib/llvm-project/clang/lib/AST/Decl.cpp +++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp @@ -394,7 +394,6 @@ void LinkageComputer::mergeTemplateLV( shouldConsiderTemplateVisibility(fn, specInfo); FunctionTemplateDecl *temp = specInfo->getTemplate(); - // Merge information from the template declaration. LinkageInfo tempLV = getLVForDecl(temp, computation); // The linkage of the specialization should be consistent with the @@ -468,11 +467,16 @@ void LinkageComputer::mergeTemplateLV( // Merge information from the template parameters, but ignore // visibility if we're only considering template arguments. - ClassTemplateDecl *temp = spec->getSpecializedTemplate(); - LinkageInfo tempLV = + // Merge information from the template declaration. + LinkageInfo tempLV = getLVForDecl(temp, computation); + // The linkage of the specialization should be consistent with the + // template declaration. + LV.setLinkage(tempLV.getLinkage()); + + LinkageInfo paramsLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); - LV.mergeMaybeWithVisibility(tempLV, + LV.mergeMaybeWithVisibility(paramsLV, considerVisibility && !hasExplicitVisibilityAlready(computation)); // Merge information from the template arguments. We ignore @@ -520,7 +524,6 @@ void LinkageComputer::mergeTemplateLV(LinkageInfo &LV, // Merge information from the template parameters, but ignore // visibility if we're only considering template arguments. - VarTemplateDecl *temp = spec->getSpecializedTemplate(); LinkageInfo tempLV = getLVForTemplateParameterList(temp->getTemplateParameters(), computation); @@ -1077,7 +1080,6 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, // Finally, merge in information from the class. LV.mergeMaybeWithVisibility(classLV, considerClassVisibility); - return LV; } diff --git a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp index cd14ff4fb970..01d80dd49e10 100644 --- a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp @@ -5269,10 +5269,14 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, } } bool Cond; - if (IS->isConsteval()) + if (IS->isConsteval()) { Cond = IS->isNonNegatedConsteval(); - else if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), - Cond)) + // If we are not in a constant context, if consteval should not evaluate + // to true. + if (!Info.InConstantContext) + Cond = !Cond; + } else if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), + Cond)) return ESR_Failed; if (const Stmt *SubStmt = Cond ? IS->getThen() : IS->getElse()) { diff --git a/contrib/llvm-project/clang/lib/Analysis/CFG.cpp b/contrib/llvm-project/clang/lib/Analysis/CFG.cpp index 614d94ae31a6..84178ff488a5 100644 --- a/contrib/llvm-project/clang/lib/Analysis/CFG.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/CFG.cpp @@ -1659,9 +1659,13 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { appendInitializer(Block, I); if (Init) { + // If the initializer is an ArrayInitLoopExpr, we want to extract the + // initializer, that's used for each element. + const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init); + findConstructionContexts( ConstructionContextLayer::create(cfg->getBumpVectorContext(), I), - Init); + AILE ? AILE->getSubExpr() : Init); if (HasTemporaries) { // For expression with temporaries go directly to subexpression to omit @@ -2928,12 +2932,30 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { } } + // If we bind to a tuple-like type, we iterate over the HoldingVars, and + // create a DeclStmt for each of them. + if (const auto *DD = dyn_cast<DecompositionDecl>(VD)) { + for (auto BD : llvm::reverse(DD->bindings())) { + if (auto *VD = BD->getHoldingVar()) { + DeclGroupRef DG(VD); + DeclStmt *DSNew = + new (Context) DeclStmt(DG, VD->getLocation(), GetEndLoc(VD)); + cfg->addSyntheticDeclStmt(DSNew, DS); + Block = VisitDeclSubExpr(DSNew); + } + } + } + autoCreateBlock(); appendStmt(Block, DS); + // If the initializer is an ArrayInitLoopExpr, we want to extract the + // initializer, that's used for each element. + const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init); + findConstructionContexts( ConstructionContextLayer::create(cfg->getBumpVectorContext(), DS), - Init); + AILE ? AILE->getSubExpr() : Init); // Keep track of the last non-null block, as 'Block' can be nulled out // if the initializer expression is something like a 'while' in a @@ -3340,9 +3362,20 @@ CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { CFGBlock *LastBlock = VisitNoRecurse(E, asc); + + unsigned Idx = 0; for (LambdaExpr::capture_init_iterator it = E->capture_init_begin(), - et = E->capture_init_end(); it != et; ++it) { + et = E->capture_init_end(); + it != et; ++it, ++Idx) { if (Expr *Init = *it) { + // If the initializer is an ArrayInitLoopExpr, we want to extract the + // initializer, that's used for each element. + const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init); + + findConstructionContexts(ConstructionContextLayer::create( + cfg->getBumpVectorContext(), {E, Idx}), + AILE ? AILE->getSubExpr() : Init); + CFGBlock *Tmp = Visit(Init); if (Tmp) LastBlock = Tmp; @@ -5616,6 +5649,12 @@ static void print_construction_context(raw_ostream &OS, Stmts.push_back(TOCC->getConstructorAfterElision()); break; } + case ConstructionContext::LambdaCaptureKind: { + const auto *LCC = cast<LambdaCaptureConstructionContext>(CC); + Helper.handledStmt(const_cast<LambdaExpr *>(LCC->getLambdaExpr()), OS); + OS << "+" << LCC->getIndex(); + return; + } case ConstructionContext::ArgumentKind: { const auto *ACC = cast<ArgumentConstructionContext>(CC); if (const Stmt *BTE = ACC->getCXXBindTemporaryExpr()) { diff --git a/contrib/llvm-project/clang/lib/Analysis/ConstructionContext.cpp b/contrib/llvm-project/clang/lib/Analysis/ConstructionContext.cpp index 6ba1e2173d2c..8a862c06f13a 100644 --- a/contrib/llvm-project/clang/lib/Analysis/ConstructionContext.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/ConstructionContext.cpp @@ -156,6 +156,12 @@ const ConstructionContext *ConstructionContext::createBoundTemporaryFromLayers( return create<CXX17ElidedCopyConstructorInitializerConstructionContext>( C, I, BTE); } + case ConstructionContextItem::LambdaCaptureKind: { + assert(ParentLayer->isLast()); + const auto *E = cast<LambdaExpr>(ParentItem.getStmt()); + return create<LambdaCaptureConstructionContext>(C, E, + ParentItem.getIndex()); + } } // switch (ParentItem.getKind()) llvm_unreachable("Unexpected construction context with destructor!"); @@ -200,6 +206,11 @@ const ConstructionContext *ConstructionContext::createFromLayers( case ConstructionContextItem::ElidableConstructorKind: { llvm_unreachable("The argument needs to be materialized first!"); } + case ConstructionContextItem::LambdaCaptureKind: { + assert(TopLayer->isLast()); + const auto *E = cast<LambdaExpr>(TopItem.getStmt()); + return create<LambdaCaptureConstructionContext>(C, E, TopItem.getIndex()); + } case ConstructionContextItem::InitializerKind: { assert(TopLayer->isLast()); const CXXCtorInitializer *I = TopItem.getCXXCtorInitializer(); diff --git a/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp index e3bb902b1fe9..c876eaa6358a 100644 --- a/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -455,14 +455,16 @@ const Stmt *ExprMutationAnalyzer::findRangeLoopMutation(const Expr *Exp) { // array is considered modified if the loop-variable is a non-const reference. const auto DeclStmtToNonRefToArray = declStmt(hasSingleDecl(varDecl(hasType( hasUnqualifiedDesugaredType(referenceType(pointee(arrayType()))))))); - const auto RefToArrayRefToElements = match( - findAll(stmt(cxxForRangeStmt( - hasLoopVariable(varDecl(hasType(nonConstReferenceType())) - .bind(NodeID<Decl>::value)), - hasRangeStmt(DeclStmtToNonRefToArray), - hasRangeInit(canResolveToExpr(equalsNode(Exp))))) - .bind("stmt")), - Stm, Context); + const auto RefToArrayRefToElements = + match(findAll(stmt(cxxForRangeStmt( + hasLoopVariable( + varDecl(anyOf(hasType(nonConstReferenceType()), + hasType(nonConstPointerType()))) + .bind(NodeID<Decl>::value)), + hasRangeStmt(DeclStmtToNonRefToArray), + hasRangeInit(canResolveToExpr(equalsNode(Exp))))) + .bind("stmt")), + Stm, Context); if (const auto *BadRangeInitFromArray = selectFirst<Stmt>("stmt", RefToArrayRefToElements)) diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index 5105999741e6..216f41bdee1c 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -113,16 +113,27 @@ BoolValue &DataflowAnalysisContext::getOrCreateNegation(BoolValue &Val) { BoolValue &DataflowAnalysisContext::getOrCreateImplication(BoolValue &LHS, BoolValue &RHS) { - return &LHS == &RHS ? getBoolLiteralValue(true) - : getOrCreateDisjunction(getOrCreateNegation(LHS), RHS); + if (&LHS == &RHS) + return getBoolLiteralValue(true); + + auto Res = ImplicationVals.try_emplace(std::make_pair(&LHS, &RHS), nullptr); + if (Res.second) + Res.first->second = + &takeOwnership(std::make_unique<ImplicationValue>(LHS, RHS)); + return *Res.first->second; } BoolValue &DataflowAnalysisContext::getOrCreateIff(BoolValue &LHS, BoolValue &RHS) { - return &LHS == &RHS - ? getBoolLiteralValue(true) - : getOrCreateConjunction(getOrCreateImplication(LHS, RHS), - getOrCreateImplication(RHS, LHS)); + if (&LHS == &RHS) + return getBoolLiteralValue(true); + + auto Res = BiconditionalVals.try_emplace(makeCanonicalBoolValuePair(LHS, RHS), + nullptr); + if (Res.second) + Res.first->second = + &takeOwnership(std::make_unique<BiconditionalValue>(LHS, RHS)); + return *Res.first->second; } AtomicBoolValue &DataflowAnalysisContext::makeFlowConditionToken() { @@ -199,18 +210,18 @@ void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( if (!Res.second) return; - auto ConstraintsIT = FlowConditionConstraints.find(&Token); - if (ConstraintsIT == FlowConditionConstraints.end()) { + auto ConstraintsIt = FlowConditionConstraints.find(&Token); + if (ConstraintsIt == FlowConditionConstraints.end()) { Constraints.insert(&Token); } else { // Bind flow condition token via `iff` to its set of constraints: // FC <=> (C1 ^ C2 ^ ...), where Ci are constraints - Constraints.insert(&getOrCreateIff(Token, *ConstraintsIT->second)); + Constraints.insert(&getOrCreateIff(Token, *ConstraintsIt->second)); } - auto DepsIT = FlowConditionDeps.find(&Token); - if (DepsIT != FlowConditionDeps.end()) { - for (AtomicBoolValue *DepToken : DepsIT->second) { + auto DepsIt = FlowConditionDeps.find(&Token); + if (DepsIt != FlowConditionDeps.end()) { + for (AtomicBoolValue *DepToken : DepsIt->second) { addTransitiveFlowConditionConstraints(*DepToken, Constraints, VisitedTokens); } @@ -220,10 +231,10 @@ void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( BoolValue &DataflowAnalysisContext::substituteBoolValue( BoolValue &Val, llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) { - auto IT = SubstitutionsCache.find(&Val); - if (IT != SubstitutionsCache.end()) { + auto It = SubstitutionsCache.find(&Val); + if (It != SubstitutionsCache.end()) { // Return memoized result of substituting this boolean value. - return *IT->second; + return *It->second; } // Handle substitution on the boolean value (and its subvalues), saving the @@ -258,6 +269,24 @@ BoolValue &DataflowAnalysisContext::substituteBoolValue( Result = &getOrCreateConjunction(LeftSub, RightSub); break; } + case Value::Kind::Implication: { + auto &IV = *cast<ImplicationValue>(&Val); + auto &LeftSub = + substituteBoolValue(IV.getLeftSubValue(), SubstitutionsCache); + auto &RightSub = + substituteBoolValue(IV.getRightSubValue(), SubstitutionsCache); + Result = &getOrCreateImplication(LeftSub, RightSub); + break; + } + case Value::Kind::Biconditional: { + auto &BV = *cast<BiconditionalValue>(&Val); + auto &LeftSub = + substituteBoolValue(BV.getLeftSubValue(), SubstitutionsCache); + auto &RightSub = + substituteBoolValue(BV.getRightSubValue(), SubstitutionsCache); + Result = &getOrCreateIff(LeftSub, RightSub); + break; + } default: llvm_unreachable("Unhandled Value Kind"); } @@ -280,19 +309,19 @@ BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowCondition( BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache( AtomicBoolValue &Token, llvm::DenseMap<BoolValue *, BoolValue *> &SubstitutionsCache) { - auto ConstraintsIT = FlowConditionConstraints.find(&Token); - if (ConstraintsIT == FlowConditionConstraints.end()) { + auto ConstraintsIt = FlowConditionConstraints.find(&Token); + if (ConstraintsIt == FlowConditionConstraints.end()) { return getBoolLiteralValue(true); } - auto DepsIT = FlowConditionDeps.find(&Token); - if (DepsIT != FlowConditionDeps.end()) { - for (AtomicBoolValue *DepToken : DepsIT->second) { + auto DepsIt = FlowConditionDeps.find(&Token); + if (DepsIt != FlowConditionDeps.end()) { + for (AtomicBoolValue *DepToken : DepsIt->second) { auto &NewDep = buildAndSubstituteFlowConditionWithCache( *DepToken, SubstitutionsCache); SubstitutionsCache[DepToken] = &NewDep; } } - return substituteBoolValue(*ConstraintsIT->second, SubstitutionsCache); + return substituteBoolValue(*ConstraintsIt->second, SubstitutionsCache); } void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) { diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 2b6cd0c4f857..f6f71e34b892 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -200,6 +200,42 @@ Environment::Environment(DataflowAnalysisContext &DACtx, } } +Environment Environment::pushCall(const CallExpr *Call) const { + Environment Env(*this); + + // FIXME: Currently this only works if the callee is never a method and the + // same callee is never analyzed from multiple separate callsites. To + // generalize this, we'll need to store a "context" field (probably a stack of + // `const CallExpr *`s) in the `Environment`, and then change the + // `DataflowAnalysisContext` class to hold a map from contexts to "frames", + // where each frame stores its own version of what are currently the + // `DeclToLoc`, `ExprToLoc`, and `ThisPointeeLoc` fields. + + const auto *FuncDecl = Call->getDirectCallee(); + assert(FuncDecl != nullptr); + assert(FuncDecl->getBody() != nullptr); + // FIXME: In order to allow the callee to reference globals, we probably need + // to call `initGlobalVars` here in some way. + + auto ParamIt = FuncDecl->param_begin(); + auto ArgIt = Call->arg_begin(); + auto ArgEnd = Call->arg_end(); + + // FIXME: Parameters don't always map to arguments 1:1; examples include + // overloaded operators implemented as member functions, and parameter packs. + for (; ArgIt != ArgEnd; ++ParamIt, ++ArgIt) { + assert(ParamIt != FuncDecl->param_end()); + + const VarDecl *Param = *ParamIt; + const Expr *Arg = *ArgIt; + auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference); + assert(ArgLoc != nullptr); + Env.setStorageLocation(*Param, *ArgLoc); + } + + return Env; +} + bool Environment::equivalentTo(const Environment &Other, Environment::ValueModel &Model) const { assert(DACtx == Other.DACtx); @@ -352,16 +388,16 @@ void Environment::setValue(const StorageLocation &Loc, Value &Val) { } } - auto IT = MemberLocToStruct.find(&Loc); - if (IT != MemberLocToStruct.end()) { + auto It = MemberLocToStruct.find(&Loc); + if (It != MemberLocToStruct.end()) { // `Loc` is the location of a struct member so we need to also update the // value of the member in the corresponding `StructValue`. - assert(IT->second.first != nullptr); - StructValue &StructVal = *IT->second.first; + assert(It->second.first != nullptr); + StructValue &StructVal = *It->second.first; - assert(IT->second.second != nullptr); - const ValueDecl &Member = *IT->second.second; + assert(It->second.second != nullptr); + const ValueDecl &Member = *It->second.second; StructVal.setChild(Member, Val); } diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp index 309ff0682f50..714ad08643ed 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp @@ -96,6 +96,20 @@ public: S = formatv("(not\n{0})", debugString(N.getSubVal(), Depth + 1)); break; } + case Value::Kind::Implication: { + auto &IV = cast<ImplicationValue>(B); + auto L = debugString(IV.getLeftSubValue(), Depth + 1); + auto R = debugString(IV.getRightSubValue(), Depth + 1); + S = formatv("(=>\n{0}\n{1})", L, R); + break; + } + case Value::Kind::Biconditional: { + auto &BV = cast<BiconditionalValue>(B); + auto L = debugString(BV.getLeftSubValue(), Depth + 1); + auto R = debugString(BV.getRightSubValue(), Depth + 1); + S = formatv("(=\n{0}\n{1})", L, R); + break; + } default: llvm_unreachable("Unhandled value kind"); } diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 500e1a7a9390..bbf7526adce9 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -20,7 +20,9 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" +#include "clang/Analysis/FlowSensitive/NoopAnalysis.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/OperatorKinds.h" @@ -46,8 +48,9 @@ static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { public: - TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env) - : StmtToEnv(StmtToEnv), Env(Env) {} + TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, + TransferOptions Options) + : StmtToEnv(StmtToEnv), Env(Env), Options(Options) {} void VisitBinaryOperator(const BinaryOperator *S) { const Expr *LHS = S->getLHS(); @@ -503,6 +506,35 @@ public: if (ArgLoc == nullptr) return; Env.setStorageLocation(*S, *ArgLoc); + } else if (const FunctionDecl *F = S->getDirectCallee()) { + // This case is for context-sensitive analysis, which we only do if we + // have the callee body available in the translation unit. + if (!Options.ContextSensitive || F->getBody() == nullptr) + return; + + auto &ASTCtx = F->getASTContext(); + + // FIXME: Cache these CFGs. + auto CFCtx = ControlFlowContext::build(F, F->getBody(), &ASTCtx); + // FIXME: Handle errors here and below. + assert(CFCtx); + auto ExitBlock = CFCtx->getCFG().getExit().getBlockID(); + + auto CalleeEnv = Env.pushCall(S); + + // FIXME: Use the same analysis as the caller for the callee. + DataflowAnalysisOptions Options; + auto Analysis = NoopAnalysis(ASTCtx, Options); + + auto BlockToOutputState = + dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv); + assert(BlockToOutputState); + assert(ExitBlock < BlockToOutputState->size()); + + auto ExitState = (*BlockToOutputState)[ExitBlock]; + assert(ExitState); + + Env = ExitState->Env; } } @@ -564,11 +596,11 @@ public: Env.setValue(Loc, *Val); if (Type->isStructureOrClassType()) { - for (auto IT : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) { - const FieldDecl *Field = std::get<0>(IT); + for (auto It : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) { + const FieldDecl *Field = std::get<0>(It); assert(Field != nullptr); - const Expr *Init = std::get<1>(IT); + const Expr *Init = std::get<1>(It); assert(Init != nullptr); if (Value *InitVal = Env.getValue(*Init, SkipPast::None)) @@ -633,10 +665,12 @@ private: const StmtToEnvMap &StmtToEnv; Environment &Env; + TransferOptions Options; }; -void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) { - TransferVisitor(StmtToEnv, Env).Visit(&S); +void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, + TransferOptions Options) { + TransferVisitor(StmtToEnv, Env, Options).Visit(&S); } } // namespace dataflow diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 6ce9dd55914d..fbb521763ee6 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -47,9 +47,9 @@ public: : CFCtx(CFCtx), BlockToState(BlockToState) {} const Environment *getEnvironment(const Stmt &S) const override { - auto BlockIT = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S)); - assert(BlockIT != CFCtx.getStmtToBlock().end()); - const auto &State = BlockToState[BlockIT->getSecond()->getBlockID()]; + auto BlockIt = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S)); + assert(BlockIt != CFCtx.getStmtToBlock().end()); + const auto &State = BlockToState[BlockIt->getSecond()->getBlockID()]; assert(State); return &State.value().Env; } @@ -74,8 +74,9 @@ static int blockIndexInPredecessor(const CFGBlock &Pred, class TerminatorVisitor : public ConstStmtVisitor<TerminatorVisitor> { public: TerminatorVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env, - int BlockSuccIdx) - : StmtToEnv(StmtToEnv), Env(Env), BlockSuccIdx(BlockSuccIdx) {} + int BlockSuccIdx, TransferOptions TransferOpts) + : StmtToEnv(StmtToEnv), Env(Env), BlockSuccIdx(BlockSuccIdx), + TransferOpts(TransferOpts) {} void VisitIfStmt(const IfStmt *S) { auto *Cond = S->getCond(); @@ -118,7 +119,7 @@ private: void extendFlowCondition(const Expr &Cond) { // The terminator sub-expression might not be evaluated. if (Env.getStorageLocation(Cond, SkipPast::None) == nullptr) - transfer(StmtToEnv, Cond, Env); + transfer(StmtToEnv, Cond, Env, TransferOpts); // FIXME: The flow condition must be an r-value, so `SkipPast::None` should // suffice. @@ -150,6 +151,7 @@ private: const StmtToEnvMap &StmtToEnv; Environment &Env; int BlockSuccIdx; + TransferOptions TransferOpts; }; /// Computes the input state for a given basic block by joining the output @@ -217,7 +219,8 @@ static TypeErasedDataflowAnalysisState computeBlockInputState( if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) { const StmtToEnvMapImpl StmtToEnv(CFCtx, BlockStates); TerminatorVisitor(StmtToEnv, PredState.Env, - blockIndexInPredecessor(*Pred, Block)) + blockIndexInPredecessor(*Pred, Block), + Analysis.builtinTransferOptions()) .Visit(PredTerminatorStmt); } } @@ -253,7 +256,8 @@ static void transferCFGStmt( assert(S != nullptr); if (Analysis.applyBuiltinTransfer()) - transfer(StmtToEnvMapImpl(CFCtx, BlockStates), *S, State.Env); + transfer(StmtToEnvMapImpl(CFCtx, BlockStates), *S, State.Env, + Analysis.builtinTransferOptions()); Analysis.transferTypeErased(S, State.Lattice, State.Env); if (HandleTransferredStmt != nullptr) diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp index 6a3948bd1fea..cd1fd708a43a 100644 --- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp @@ -221,6 +221,18 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) { UnprocessedSubVals.push(&N->getSubVal()); break; } + case Value::Kind::Implication: { + auto *I = cast<ImplicationValue>(Val); + UnprocessedSubVals.push(&I->getLeftSubValue()); + UnprocessedSubVals.push(&I->getRightSubValue()); + break; + } + case Value::Kind::Biconditional: { + auto *B = cast<BiconditionalValue>(Val); + UnprocessedSubVals.push(&B->getLeftSubValue()); + UnprocessedSubVals.push(&B->getRightSubValue()); + break; + } case Value::Kind::AtomicBool: { Atomics[Var] = cast<AtomicBoolValue>(Val); break; @@ -263,30 +275,52 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) { const Variable LeftSubVar = GetVar(&C->getLeftSubValue()); const Variable RightSubVar = GetVar(&C->getRightSubValue()); - // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v !B)` - // which is already in conjunctive normal form. Below we add each of the - // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar)); - Formula.addClause(negLit(Var), posLit(RightSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar)); + if (LeftSubVar == RightSubVar) { + // `X <=> (A ^ A)` is equivalent to `(!X v A) ^ (X v !A)` which is + // already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + Formula.addClause(negLit(Var), posLit(LeftSubVar)); + Formula.addClause(posLit(Var), negLit(LeftSubVar)); - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&C->getLeftSubValue()); - UnprocessedSubVals.push(&C->getRightSubValue()); + // Visit a sub-value of `Val` (pick any, they are identical). + UnprocessedSubVals.push(&C->getLeftSubValue()); + } else { + // `X <=> (A ^ B)` is equivalent to `(!X v A) ^ (!X v B) ^ (X v !A v !B)` + // which is already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + Formula.addClause(negLit(Var), posLit(LeftSubVar)); + Formula.addClause(negLit(Var), posLit(RightSubVar)); + Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar)); + + // Visit the sub-values of `Val`. + UnprocessedSubVals.push(&C->getLeftSubValue()); + UnprocessedSubVals.push(&C->getRightSubValue()); + } } else if (auto *D = dyn_cast<DisjunctionValue>(Val)) { const Variable LeftSubVar = GetVar(&D->getLeftSubValue()); const Variable RightSubVar = GetVar(&D->getRightSubValue()); - // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v !B)` - // which is already in conjunctive normal form. Below we add each of the - // conjuncts of the latter expression to the result. - Formula.addClause(negLit(Var), posLit(LeftSubVar), posLit(RightSubVar)); - Formula.addClause(posLit(Var), negLit(LeftSubVar)); - Formula.addClause(posLit(Var), negLit(RightSubVar)); + if (LeftSubVar == RightSubVar) { + // `X <=> (A v A)` is equivalent to `(!X v A) ^ (X v !A)` which is + // already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + Formula.addClause(negLit(Var), posLit(LeftSubVar)); + Formula.addClause(posLit(Var), negLit(LeftSubVar)); - // Visit the sub-values of `Val`. - UnprocessedSubVals.push(&D->getLeftSubValue()); - UnprocessedSubVals.push(&D->getRightSubValue()); + // Visit a sub-value of `Val` (pick any, they are identical). + UnprocessedSubVals.push(&D->getLeftSubValue()); + } else { + // `X <=> (A v B)` is equivalent to `(!X v A v B) ^ (X v !A) ^ (X v !B)` + // which is already in conjunctive normal form. Below we add each of the + // conjuncts of the latter expression to the result. + Formula.addClause(negLit(Var), posLit(LeftSubVar), posLit(RightSubVar)); + Formula.addClause(posLit(Var), negLit(LeftSubVar)); + Formula.addClause(posLit(Var), negLit(RightSubVar)); + + // Visit the sub-values of `Val`. + UnprocessedSubVals.push(&D->getLeftSubValue()); + UnprocessedSubVals.push(&D->getRightSubValue()); + } } else if (auto *N = dyn_cast<NegationValue>(Val)) { const Variable SubVar = GetVar(&N->getSubVal()); @@ -298,6 +332,46 @@ BooleanFormula buildBooleanFormula(const llvm::DenseSet<BoolValue *> &Vals) { // Visit the sub-values of `Val`. UnprocessedSubVals.push(&N->getSubVal()); + } else if (auto *I = dyn_cast<ImplicationValue>(Val)) { + const Variable LeftSubVar = GetVar(&I->getLeftSubValue()); + const Variable RightSubVar = GetVar(&I->getRightSubValue()); + + // `X <=> (A => B)` is equivalent to + // `(X v A) ^ (X v !B) ^ (!X v !A v B)` which is already in + // conjunctive normal form. Below we add each of the conjuncts of the + // latter expression to the result. + Formula.addClause(posLit(Var), posLit(LeftSubVar)); + Formula.addClause(posLit(Var), negLit(RightSubVar)); + Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar)); + + // Visit the sub-values of `Val`. + UnprocessedSubVals.push(&I->getLeftSubValue()); + UnprocessedSubVals.push(&I->getRightSubValue()); + } else if (auto *B = dyn_cast<BiconditionalValue>(Val)) { + const Variable LeftSubVar = GetVar(&B->getLeftSubValue()); + const Variable RightSubVar = GetVar(&B->getRightSubValue()); + + if (LeftSubVar == RightSubVar) { + // `X <=> (A <=> A)` is equvalent to `X` which is already in + // conjunctive normal form. Below we add each of the conjuncts of the + // latter expression to the result. + Formula.addClause(posLit(Var)); + + // No need to visit the sub-values of `Val`. + } else { + // `X <=> (A <=> B)` is equivalent to + // `(X v A v B) ^ (X v !A v !B) ^ (!X v A v !B) ^ (!X v !A v B)` which is + // already in conjunctive normal form. Below we add each of the conjuncts + // of the latter expression to the result. + Formula.addClause(posLit(Var), posLit(LeftSubVar), posLit(RightSubVar)); + Formula.addClause(posLit(Var), negLit(LeftSubVar), negLit(RightSubVar)); + Formula.addClause(negLit(Var), posLit(LeftSubVar), negLit(RightSubVar)); + Formula.addClause(negLit(Var), negLit(LeftSubVar), posLit(RightSubVar)); + + // Visit the sub-values of `Val`. + UnprocessedSubVals.push(&B->getLeftSubValue()); + UnprocessedSubVals.push(&B->getRightSubValue()); + } } } diff --git a/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp b/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp index 6c601c290c92..ff7f3ebe28f8 100644 --- a/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp +++ b/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp @@ -72,6 +72,11 @@ bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const { bool alive = false; for (const BindingDecl *BD : DD->bindings()) alive |= liveBindings.contains(BD); + + // Note: the only known case this condition is necessary, is when a bindig + // to a tuple-like structure is created. The HoldingVar initializers have a + // DeclRefExpr to the DecompositionDecl. + alive |= liveDecls.contains(DD); return alive; } return liveDecls.contains(D); @@ -343,8 +348,12 @@ void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) { if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) { Killed = !BD->getType()->isReferenceType(); - if (Killed) + if (Killed) { + if (const auto *HV = BD->getHoldingVar()) + val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV); + val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD); + } } else if (const auto *VD = dyn_cast<VarDecl>(D)) { Killed = writeShouldKill(VD); if (Killed) @@ -371,8 +380,12 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) { const Decl* D = DR->getDecl(); bool InAssignment = LV.inAssignment[DR]; if (const auto *BD = dyn_cast<BindingDecl>(D)) { - if (!InAssignment) + if (!InAssignment) { + if (const auto *HV = BD->getHoldingVar()) + val.liveDecls = LV.DSetFact.add(val.liveDecls, HV); + val.liveBindings = LV.BSetFact.add(val.liveBindings, BD); + } } else if (const auto *VD = dyn_cast<VarDecl>(D)) { if (!InAssignment && !isAlwaysAlive(VD)) val.liveDecls = LV.DSetFact.add(val.liveDecls, VD); @@ -382,8 +395,16 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) { void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { for (const auto *DI : DS->decls()) { if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) { - for (const auto *BD : DD->bindings()) + for (const auto *BD : DD->bindings()) { + if (const auto *HV = BD->getHoldingVar()) + val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV); + val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD); + } + + // When a bindig to a tuple-like structure is created, the HoldingVar + // initializers have a DeclRefExpr to the DecompositionDecl. + val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD); } else if (const auto *VD = dyn_cast<VarDecl>(DI)) { if (!isAlwaysAlive(VD)) val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD); diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/CSKY.h b/contrib/llvm-project/clang/lib/Basic/Targets/CSKY.h index 7e932e7c86b1..6edd035d9eb8 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/CSKY.h +++ b/contrib/llvm-project/clang/lib/Basic/Targets/CSKY.h @@ -71,7 +71,7 @@ public: bool isValidCPUName(StringRef Name) const override; - virtual unsigned getMinGlobalAlign(uint64_t) const override; + unsigned getMinGlobalAlign(uint64_t) const override; ArrayRef<Builtin::Info> getTargetBuiltins() const override; diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp index 9120808e298d..ca01b44ae3a5 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/PPC.cpp @@ -849,6 +849,9 @@ void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { ? &llvm::APFloat::IEEEquad() : &llvm::APFloat::PPCDoubleDouble(); Opts.IEEE128 = 1; + if (getTriple().isOSAIX() && Opts.EnableAIXQuadwordAtomicsABI && + HasQuadwordAtomics) + MaxAtomicInlineWidth = 128; } ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const { diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/X86.h b/contrib/llvm-project/clang/lib/Basic/Targets/X86.h index 3caf5256118e..224145f4b020 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/X86.h +++ b/contrib/llvm-project/clang/lib/Basic/Targets/X86.h @@ -229,14 +229,14 @@ public: bool validateInputSize(const llvm::StringMap<bool> &FeatureMap, StringRef Constraint, unsigned Size) const override; - virtual bool + bool checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const override { if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro) return true; return TargetInfo::checkCFProtectionReturnSupported(Diags); }; - virtual bool + bool checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const override { if (CPU == llvm::X86::CK_None || CPU >= llvm::X86::CK_PentiumPro) return true; diff --git a/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h index fe6cc7a2b1c7..c1eb8a975796 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h +++ b/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h @@ -127,7 +127,7 @@ namespace CodeGen { public: SwiftABIInfo(CodeGen::CodeGenTypes &cgt) : ABIInfo(cgt) {} - bool supportsSwift() const final override { return true; } + bool supportsSwift() const final { return true; } virtual bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> types, bool asReturnValue) const = 0; diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.h b/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.h index a46f7f37141f..0768e6581acb 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.h @@ -41,6 +41,8 @@ struct CatchTypeInfo; /// Implements C++ ABI-specific code generation functions. class CGCXXABI { + friend class CodeGenModule; + protected: CodeGenModule &CGM; std::unique_ptr<MangleContext> MangleCtx; diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp index 104a30dd6b25..dfa78bf59c65 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp @@ -4473,17 +4473,22 @@ llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee, // they are nested within. SmallVector<llvm::OperandBundleDef, 1> CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) { - SmallVector<llvm::OperandBundleDef, 1> BundleList; // There is no need for a funclet operand bundle if we aren't inside a // funclet. if (!CurrentFuncletPad) - return BundleList; - - // Skip intrinsics which cannot throw. - auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts()); - if (CalleeFn && CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) - return BundleList; + return (SmallVector<llvm::OperandBundleDef, 1>()); + + // Skip intrinsics which cannot throw (as long as they don't lower into + // regular function calls in the course of IR transformations). + if (auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts())) { + if (CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) { + auto IID = CalleeFn->getIntrinsicID(); + if (!llvm::IntrinsicInst::mayLowerToFunctionCall(IID)) + return (SmallVector<llvm::OperandBundleDef, 1>()); + } + } + SmallVector<llvm::OperandBundleDef, 1> BundleList; BundleList.emplace_back("funclet", CurrentFuncletPad); return BundleList; } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp index cde31711a7db..c6696c4df775 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp @@ -2698,15 +2698,21 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, // Don't insert type test assumes if we are forcing public // visibility. !CGM.AlwaysHasLTOVisibilityPublic(RD)) { - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); + QualType Ty = QualType(RD->getTypeForDecl(), 0); + llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty); llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); + // If we already know that the call has hidden LTO visibility, emit + // @llvm.type.test(). Otherwise emit @llvm.public.type.test(), which WPD + // will convert to @llvm.type.test() if we assert at link time that we have + // whole program visibility. + llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD) + ? llvm::Intrinsic::type_test + : llvm::Intrinsic::public_type_test; llvm::Value *TypeTest = - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), - {CastedVTable, TypeId}); + Builder.CreateCall(CGM.getIntrinsic(IID), {CastedVTable, TypeId}); Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest); } } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp index 7e9e86763af9..94c48316add7 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp @@ -491,9 +491,11 @@ StringRef CGDebugInfo::getCurrentDirname() { if (!CWDName.empty()) return CWDName; - SmallString<256> CWD; - llvm::sys::fs::current_path(CWD); - return CWDName = internString(CWD); + llvm::ErrorOr<std::string> CWD = + CGM.getFileSystem()->getCurrentWorkingDirectory(); + if (!CWD) + return StringRef(); + return CWDName = internString(*CWD); } void CGDebugInfo::CreateCompileUnit() { diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp index ec459f07f307..7bbe9af7ed59 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp @@ -2837,11 +2837,13 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, // Enter the continuation block and emit a phi if required. CGF.EmitBlock(continueBB); if (msgRet.isScalar()) { - llvm::Value *v = msgRet.getScalarVal(); - llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2); - phi->addIncoming(v, nonNilPathBB); - phi->addIncoming(CGM.EmitNullConstant(ResultType), nilPathBB); - msgRet = RValue::get(phi); + // If the return type is void, do nothing + if (llvm::Value *v = msgRet.getScalarVal()) { + llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2); + phi->addIncoming(v, nonNilPathBB); + phi->addIncoming(CGM.EmitNullConstant(ResultType), nilPathBB); + msgRet = RValue::get(phi); + } } else if (msgRet.isAggregate()) { // Aggregate zeroing is handled in nilCleanupBB when it's required. } else /* isComplex() */ { diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h index 1d30c5061743..ff585efa3fce 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h @@ -186,17 +186,16 @@ public: /// Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 /// global_tid, int proc_bind) to generate code for 'proc_bind' clause. - virtual void emitProcBindClause(CodeGenFunction &CGF, - llvm::omp::ProcBindKind ProcBind, - SourceLocation Loc) override; + void emitProcBindClause(CodeGenFunction &CGF, + llvm::omp::ProcBindKind ProcBind, + SourceLocation Loc) override; /// Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 /// global_tid, kmp_int32 num_threads) to generate code for 'num_threads' /// clause. /// \param NumThreads An integer value of threads. - virtual void emitNumThreadsClause(CodeGenFunction &CGF, - llvm::Value *NumThreads, - SourceLocation Loc) override; + void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, + SourceLocation Loc) override; /// This function ought to emit, in the general case, a call to // the openmp runtime kmpc_push_num_teams. In NVPTX backend it is not needed @@ -300,12 +299,12 @@ public: /// SimpleReduction Emit reduction operation only. Used for omp simd /// directive on the host. /// ReductionKind The kind of reduction to perform. - virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, - ArrayRef<const Expr *> Privates, - ArrayRef<const Expr *> LHSExprs, - ArrayRef<const Expr *> RHSExprs, - ArrayRef<const Expr *> ReductionOps, - ReductionOptionsTy Options) override; + void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, + ArrayRef<const Expr *> Privates, + ArrayRef<const Expr *> LHSExprs, + ArrayRef<const Expr *> RHSExprs, + ArrayRef<const Expr *> ReductionOps, + ReductionOptionsTy Options) override; /// Returns specified OpenMP runtime function for the current OpenMP /// implementation. Specialized for the NVPTX device. diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp index 4ffbecdf2741..12c6b3f49c43 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp @@ -146,6 +146,7 @@ namespace clang { public: BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, @@ -159,8 +160,8 @@ namespace clang { AsmOutStream(std::move(OS)), Context(nullptr), LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, - CodeGenOpts, C, CoverageInfo)), + Gen(CreateLLVMCodeGen(Diags, InFile, std::move(FS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)) { TimerIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; @@ -171,6 +172,7 @@ namespace clang { // to use the clang diagnostic handler for IR input files. It avoids // initializing the OS field. BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, @@ -183,8 +185,8 @@ namespace clang { Context(nullptr), LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, - CodeGenOpts, C, CoverageInfo)), + Gen(CreateLLVMCodeGen(Diags, "", std::move(FS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)), CurLinkModule(Module) { TimerIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; @@ -1052,10 +1054,10 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.getPreprocessor()); std::unique_ptr<BackendConsumer> Result(new BackendConsumer( - BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getLangOpts(), std::string(InFile), std::move(LinkModules), - std::move(OS), *VMContext, CoverageInfo)); + BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(), + CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), + CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile), + std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); BEConsumer = Result.get(); // Enable generating macro debug info only when debug info is not disabled and @@ -1185,9 +1187,10 @@ void CodeGenAction::ExecuteAction() { // Set clang diagnostic handler. To do this we need to create a fake // BackendConsumer. - BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), - CI.getPreprocessorOpts(), CI.getCodeGenOpts(), - CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(), + BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(), + CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getLangOpts(), TheModule.get(), std::move(LinkModules), *VMContext, nullptr); // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be // true here because the valued names are needed for reading textual IR. diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 101080b6fe13..4e8e120d89df 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -96,16 +96,18 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) { llvm_unreachable("invalid C++ ABI kind"); } -CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, +CodeGenModule::CodeGenModule(ASTContext &C, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, + const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO, llvm::Module &M, DiagnosticsEngine &diags, CoverageSourceInfo *CoverageInfo) - : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), - PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), - Target(C.getTargetInfo()), ABI(createCXXABI(*this)), - VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)) { + : Context(C), LangOpts(C.getLangOpts()), FS(std::move(FS)), + HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), + TheModule(M), Diags(diags), Target(C.getTargetInfo()), + ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), + VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); @@ -795,18 +797,17 @@ void CodeGenModule::Release() { Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 || Arch == llvm::Triple::aarch64_be) { - getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement", - LangOpts.BranchTargetEnforcement); - - getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", - LangOpts.hasSignReturnAddress()); - - getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all", - LangOpts.isSignReturnAddressScopeAll()); - - getModule().addModuleFlag(llvm::Module::Min, - "sign-return-address-with-bkey", - !LangOpts.isSignReturnAddressWithAKey()); + if (LangOpts.BranchTargetEnforcement) + getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement", + 1); + if (LangOpts.hasSignReturnAddress()) + getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1); + if (LangOpts.isSignReturnAddressScopeAll()) + getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all", + 1); + if (!LangOpts.isSignReturnAddressWithAKey()) + getModule().addModuleFlag(llvm::Module::Min, + "sign-return-address-with-bkey", 1); } if (!CodeGenOpts.MemoryProfileOutput.empty()) { @@ -7000,4 +7001,6 @@ void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) { "Still have (unmerged) EmittedDeferredDecls deferred decls"); NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls); + + NewBuilder->ABI->MangleCtx = std::move(ABI->MangleCtx); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h index c939e7a309f5..5fbcc5ad1f5f 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h @@ -47,6 +47,10 @@ class DataLayout; class FunctionType; class LLVMContext; class IndexedInstrProfReader; + +namespace vfs { +class FileSystem; +} } namespace clang { @@ -293,6 +297,7 @@ public: private: ASTContext &Context; const LangOptions &LangOpts; + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions &CodeGenOpts; @@ -584,7 +589,8 @@ private: llvm::DenseMap<const llvm::Constant *, llvm::GlobalVariable *> RTTIProxyMap; public: - CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, + CodeGenModule(ASTContext &C, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, + const HeaderSearchOptions &headersearchopts, const PreprocessorOptions &ppopts, const CodeGenOptions &CodeGenOpts, llvm::Module &M, DiagnosticsEngine &Diags, @@ -712,6 +718,9 @@ public: ASTContext &getContext() const { return Context; } const LangOptions &getLangOpts() const { return LangOpts; } + const IntrusiveRefCntPtr<llvm::vfs::FileSystem> &getFileSystem() const { + return FS; + } const HeaderSearchOptions &getHeaderSearchOpts() const { return HeaderSearchOpts; } const PreprocessorOptions &getPreprocessorOpts() diff --git a/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp index f0003c4aab78..fc2ff15a6acd 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -707,8 +707,12 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( if (ShouldEmitCFICheck || ShouldEmitWPDInfo) { llvm::Value *VFPAddr = Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset); + llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD) + ? llvm::Intrinsic::type_test + : llvm::Intrinsic::public_type_test; + CheckResult = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::type_test), + CGM.getIntrinsic(IID), {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId}); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 2bc1e8e8c5b9..f0c45654f8d9 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -782,7 +782,7 @@ public: LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD) override; - virtual bool + bool isPermittedToBeHomogeneousAggregate(const CXXRecordDecl *RD) const override; private: diff --git a/contrib/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp b/contrib/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp index 8e97a298ce7f..c9a5e56c72c7 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/VirtualFileSystem.h" #include <memory> using namespace clang; @@ -32,6 +33,7 @@ namespace { class CodeGeneratorImpl : public CodeGenerator { DiagnosticsEngine &Diags; ASTContext *Ctx; + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions CodeGenOpts; // Intentionally copied in. @@ -74,11 +76,12 @@ namespace { public: CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, const HeaderSearchOptions &HSO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO, llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), + : Diags(diags), Ctx(nullptr), FS(std::move(FS)), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), CoverageInfo(CoverageInfo), M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) { @@ -158,7 +161,7 @@ namespace { if (auto TVSDKVersion = Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion()) M->setDarwinTargetVariantSDKVersion(*TVSDKVersion); - Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, + Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags, CoverageInfo)); @@ -356,11 +359,14 @@ llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName, return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C); } -CodeGenerator *clang::CreateLLVMCodeGen( - DiagnosticsEngine &Diags, llvm::StringRef ModuleName, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, - llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { - return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, - PreprocessorOpts, CGO, C, CoverageInfo); +CodeGenerator * +clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PreprocessorOpts, + const CodeGenOptions &CGO, llvm::LLVMContext &C, + CoverageSourceInfo *CoverageInfo) { + return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS), + HeaderSearchOpts, PreprocessorOpts, CGO, C, + CoverageInfo); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/contrib/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index d03e5bd50873..f6eaa35b4873 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -45,6 +45,7 @@ class PCHContainerGenerator : public ASTConsumer { const std::string OutputFileName; ASTContext *Ctx; ModuleMap &MMap; + IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; const HeaderSearchOptions &HeaderSearchOpts; const PreprocessorOptions &PreprocessorOpts; CodeGenOptions CodeGenOpts; @@ -144,6 +145,7 @@ public: : Diags(CI.getDiagnostics()), MainFileName(MainFileName), OutputFileName(OutputFileName), Ctx(nullptr), MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), + FS(&CI.getVirtualFileSystem()), HeaderSearchOpts(CI.getHeaderSearchOpts()), PreprocessorOpts(CI.getPreprocessorOpts()), TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), @@ -173,7 +175,7 @@ public: M.reset(new llvm::Module(MainFileName, *VMContext)); M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); Builder.reset(new CodeGen::CodeGenModule( - *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); + *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); // Prepare CGDebugInfo to emit debug info for a clang module. auto *DI = Builder->getModuleDebugInfo(); diff --git a/contrib/llvm-project/clang/lib/CodeGen/SanitizerMetadata.h b/contrib/llvm-project/clang/lib/CodeGen/SanitizerMetadata.h index bcad32ce31df..f5dd0e503cc0 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/SanitizerMetadata.h +++ b/contrib/llvm-project/clang/lib/CodeGen/SanitizerMetadata.h @@ -20,7 +20,6 @@ namespace llvm { class GlobalVariable; class Instruction; -class MDNode; } // namespace llvm namespace clang { diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp index 5c49db2f0837..a64909d9a6e7 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -548,6 +548,11 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, if (CPUArg) checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures, Triple, CPUArgFPUID); + + // TODO Handle -mtune=. Suppress -Wunused-command-line-argument as a + // longstanding behavior. + (void)Args.getLastArg(options::OPT_mtune_EQ); + // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. unsigned FPUID = llvm::ARM::FK_INVALID; const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp index bcaecf4b2d98..7817ec595ceb 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -107,6 +107,10 @@ const char *ppc::getPPCAsmModeForCPU(StringRef Name) { void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector<StringRef> &Features) { + // TODO Handle -mtune=. Suppress -Wunused-command-line-argument as a + // longstanding behavior. + (void)Args.getLastArg(options::OPT_mtune_EQ); + if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe) Features.push_back("+spe"); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp index 3044c2d92d21..b62a025c5072 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp @@ -5112,6 +5112,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mabi=vec-default"); } + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ_quadword_atomics)) { + if (!Triple.isOSAIX() || Triple.isPPC32()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << RawTriple.str(); + CmdArgs.push_back("-mabi=quadword-atomics"); + } + if (Arg *A = Args.getLastArg(options::OPT_mlong_double_128)) { // Emit the unsupported option error until the Clang's library integration // support for 128-bit long double is available for AIX. diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp index e5451c20a00c..e49e8b0bf7d1 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -489,12 +489,14 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const { Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Vptr; - if (IsX86_64 || IsMIPS64) { + if (IsAArch64 || IsX86_64 || IsMIPS64) { Res |= SanitizerKind::Leak; Res |= SanitizerKind::Thread; } if (IsX86 || IsX86_64) { Res |= SanitizerKind::Function; + } + if (IsAArch64 || IsX86 || IsX86_64) { Res |= SanitizerKind::SafeStack; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; @@ -502,8 +504,6 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const { if (IsAArch64 || IsX86_64) { Res |= SanitizerKind::KernelAddress; Res |= SanitizerKind::KernelMemory; - } - if (IsX86_64) { Res |= SanitizerKind::Memory; } return Res; diff --git a/contrib/llvm-project/clang/lib/Edit/EditedSource.cpp b/contrib/llvm-project/clang/lib/Edit/EditedSource.cpp index ee57660b8c72..a3386b2489b0 100644 --- a/contrib/llvm-project/clang/lib/Edit/EditedSource.cpp +++ b/contrib/llvm-project/clang/lib/Edit/EditedSource.cpp @@ -84,11 +84,11 @@ bool EditedSource::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) { deconstructMacroArgLoc(OrigLoc, ExpLoc, ArgUse); auto I = ExpansionToArgMap.find(ExpLoc); if (I != ExpansionToArgMap.end() && - find_if(I->second, [&](const MacroArgUse &U) { + llvm::any_of(I->second, [&](const MacroArgUse &U) { return ArgUse.Identifier == U.Identifier && std::tie(ArgUse.ImmediateExpansionLoc, ArgUse.UseLoc) != std::tie(U.ImmediateExpansionLoc, U.UseLoc); - }) != I->second.end()) { + })) { // Trying to write in a macro argument input that has already been // written by a previous commit for another expansion of the same macro // argument name. For example: diff --git a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp index 66f03dcb53a1..3f9b68ccbb39 100644 --- a/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp +++ b/contrib/llvm-project/clang/lib/Format/FormatTokenLexer.cpp @@ -239,55 +239,6 @@ bool FormatTokenLexer::tryMergeCSharpStringLiteral() { if (Tokens.size() < 2) return false; - // Interpolated strings could contain { } with " characters inside. - // $"{x ?? "null"}" - // should not be split into $"{x ?? ", null, "}" but should treated as a - // single string-literal. - // - // We opt not to try and format expressions inside {} within a C# - // interpolated string. Formatting expressions within an interpolated string - // would require similar work as that done for JavaScript template strings - // in `handleTemplateStrings()`. - auto &CSharpInterpolatedString = *(Tokens.end() - 2); - if (CSharpInterpolatedString->getType() == TT_CSharpStringLiteral && - (CSharpInterpolatedString->TokenText.startswith(R"($")") || - CSharpInterpolatedString->TokenText.startswith(R"($@")"))) { - int UnmatchedOpeningBraceCount = 0; - - auto TokenTextSize = CSharpInterpolatedString->TokenText.size(); - for (size_t Index = 0; Index < TokenTextSize; ++Index) { - char C = CSharpInterpolatedString->TokenText[Index]; - if (C == '{') { - // "{{" inside an interpolated string is an escaped '{' so skip it. - if (Index + 1 < TokenTextSize && - CSharpInterpolatedString->TokenText[Index + 1] == '{') { - ++Index; - continue; - } - ++UnmatchedOpeningBraceCount; - } else if (C == '}') { - // "}}" inside an interpolated string is an escaped '}' so skip it. - if (Index + 1 < TokenTextSize && - CSharpInterpolatedString->TokenText[Index + 1] == '}') { - ++Index; - continue; - } - --UnmatchedOpeningBraceCount; - } - } - - if (UnmatchedOpeningBraceCount > 0) { - auto &NextToken = *(Tokens.end() - 1); - CSharpInterpolatedString->TokenText = - StringRef(CSharpInterpolatedString->TokenText.begin(), - NextToken->TokenText.end() - - CSharpInterpolatedString->TokenText.begin()); - CSharpInterpolatedString->ColumnWidth += NextToken->ColumnWidth; - Tokens.erase(Tokens.end() - 1); - return true; - } - } - // Look for @"aaaaaa" or $"aaaaaa". auto &String = *(Tokens.end() - 1); if (!String->is(tok::string_literal)) @@ -571,45 +522,105 @@ void FormatTokenLexer::tryParseJSRegexLiteral() { resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset))); } +static auto lexCSharpString(const char *Begin, const char *End, bool Verbatim, + bool Interpolated) { + auto Repeated = [&Begin, End]() { + return Begin + 1 < End && Begin[1] == Begin[0]; + }; + + // Look for a terminating '"' in the current file buffer. + // Make no effort to format code within an interpolated or verbatim string. + // + // Interpolated strings could contain { } with " characters inside. + // $"{x ?? "null"}" + // should not be split into $"{x ?? ", null, "}" but should be treated as a + // single string-literal. + // + // We opt not to try and format expressions inside {} within a C# + // interpolated string. Formatting expressions within an interpolated string + // would require similar work as that done for JavaScript template strings + // in `handleTemplateStrings()`. + for (int UnmatchedOpeningBraceCount = 0; Begin < End; ++Begin) { + switch (*Begin) { + case '\\': + if (!Verbatim) + ++Begin; + break; + case '{': + if (Interpolated) { + // {{ inside an interpolated string is escaped, so skip it. + if (Repeated()) + ++Begin; + else + ++UnmatchedOpeningBraceCount; + } + break; + case '}': + if (Interpolated) { + // }} inside an interpolated string is escaped, so skip it. + if (Repeated()) + ++Begin; + else if (UnmatchedOpeningBraceCount > 0) + --UnmatchedOpeningBraceCount; + else + return End; + } + break; + case '"': + if (UnmatchedOpeningBraceCount > 0) + break; + // "" within a verbatim string is an escaped double quote: skip it. + if (Verbatim && Repeated()) { + ++Begin; + break; + } + return Begin; + } + } + + return End; +} + void FormatTokenLexer::handleCSharpVerbatimAndInterpolatedStrings() { FormatToken *CSharpStringLiteral = Tokens.back(); - if (CSharpStringLiteral->getType() != TT_CSharpStringLiteral) + if (CSharpStringLiteral->isNot(TT_CSharpStringLiteral)) return; + auto &TokenText = CSharpStringLiteral->TokenText; + + bool Verbatim = false; + bool Interpolated = false; + if (TokenText.startswith(R"($@")")) { + Verbatim = true; + Interpolated = true; + } else if (TokenText.startswith(R"(@")")) { + Verbatim = true; + } else if (TokenText.startswith(R"($")")) { + Interpolated = true; + } + // Deal with multiline strings. - if (!(CSharpStringLiteral->TokenText.startswith(R"(@")") || - CSharpStringLiteral->TokenText.startswith(R"($@")"))) { + if (!Verbatim && !Interpolated) return; - } - const char *StrBegin = - Lex->getBufferLocation() - CSharpStringLiteral->TokenText.size(); + const char *StrBegin = Lex->getBufferLocation() - TokenText.size(); const char *Offset = StrBegin; - if (CSharpStringLiteral->TokenText.startswith(R"(@")")) - Offset += 2; - else // CSharpStringLiteral->TokenText.startswith(R"($@")") + if (Verbatim && Interpolated) Offset += 3; + else + Offset += 2; - // Look for a terminating '"' in the current file buffer. - // Make no effort to format code within an interpolated or verbatim string. - for (; Offset != Lex->getBuffer().end(); ++Offset) { - if (Offset[0] == '"') { - // "" within a verbatim string is an escaped double quote: skip it. - if (Offset + 1 < Lex->getBuffer().end() && Offset[1] == '"') - ++Offset; - else - break; - } - } + const auto End = Lex->getBuffer().end(); + Offset = lexCSharpString(Offset, End, Verbatim, Interpolated); // Make no attempt to format code properly if a verbatim string is // unterminated. - if (Offset == Lex->getBuffer().end()) + if (Offset >= End) return; StringRef LiteralText(StrBegin, Offset - StrBegin + 1); - CSharpStringLiteral->TokenText = LiteralText; + TokenText = LiteralText; // Adjust width for potentially multiline string literals. size_t FirstBreak = LiteralText.find('\n'); @@ -628,10 +639,8 @@ void FormatTokenLexer::handleCSharpVerbatimAndInterpolatedStrings() { StartColumn, Style.TabWidth, Encoding); } - SourceLocation loc = Offset < Lex->getBuffer().end() - ? Lex->getSourceLocation(Offset + 1) - : SourceMgr.getLocForEndOfFile(ID); - resetLexer(SourceMgr.getFileOffset(loc)); + assert(Offset < End); + resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1))); } void FormatTokenLexer::handleTemplateStrings() { diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp index 48cd6a394107..2dd96e68bb92 100644 --- a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp @@ -1926,6 +1926,12 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.EnableAIXExtendedAltivecABI = O.matches(OPT_mabi_EQ_vec_extabi); } + if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) { + if (!T.isOSAIX() || T.isPPC32()) + Diags.Report(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << T.str(); + } + bool NeedLocTracking = false; if (!Opts.OptRecordFile.empty()) diff --git a/contrib/llvm-project/clang/lib/Headers/stdatomic.h b/contrib/llvm-project/clang/lib/Headers/stdatomic.h index 3a0b9cc056be..318c7ca56e41 100644 --- a/contrib/llvm-project/clang/lib/Headers/stdatomic.h +++ b/contrib/llvm-project/clang/lib/Headers/stdatomic.h @@ -17,7 +17,8 @@ * explicitly disallows `stdatomic.h` in the C mode via an `#error`. Fallback * to the clang resource header until that is fully supported. */ -#if __STDC_HOSTED__ && __has_include_next(<stdatomic.h>) && !defined(_MSC_VER) +#if __STDC_HOSTED__ && \ + __has_include_next(<stdatomic.h>) && !(defined(_MSC_VER) && !defined(__cplusplus)) # include_next <stdatomic.h> #else diff --git a/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h b/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h index f11ec0aa9e75..5b0f982b62dd 100644 --- a/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h +++ b/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h @@ -21,7 +21,6 @@ namespace llvm { class Error; -class Module; namespace orc { class LLJIT; class ThreadSafeContext; diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp index 2f21b7b2fef0..aef9909a7c97 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp @@ -6344,23 +6344,27 @@ void Parser::ParseDirectDeclarator(Declarator &D) { diag::err_expected_member_name_or_semi) << (D.getDeclSpec().isEmpty() ? SourceRange() : D.getDeclSpec().getSourceRange()); - } else if (getLangOpts().CPlusPlus) { - if (Tok.isOneOf(tok::period, tok::arrow)) - Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); - else { - SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); - if (Tok.isAtStartOfLine() && Loc.isValid()) - Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) - << getLangOpts().CPlusPlus; - else - Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), - diag::err_expected_unqualified_id) - << getLangOpts().CPlusPlus; - } } else { - Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), - diag::err_expected_either) - << tok::identifier << tok::l_paren; + if (Tok.getKind() == tok::TokenKind::kw_while) { + Diag(Tok, diag::err_while_loop_outside_of_a_function); + } else if (getLangOpts().CPlusPlus) { + if (Tok.isOneOf(tok::period, tok::arrow)) + Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); + else { + SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); + if (Tok.isAtStartOfLine() && Loc.isValid()) + Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus; + else + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus; + } + } else { + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_either) + << tok::identifier << tok::l_paren; + } } D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp index 143b373e9ea5..bf73ddfd1031 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp @@ -60,7 +60,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SourceLocation &DeclEnd, SourceLocation InlineLoc) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); - SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. + SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. ObjCDeclContextSwitch ObjCDC(*this); if (Tok.is(tok::code_completion)) { @@ -99,7 +99,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); - IdentLoc = ConsumeToken(); // eat the identifier. + IdentLoc = ConsumeToken(); // eat the identifier. while (Tok.is(tok::coloncolon) && (NextToken().is(tok::identifier) || (NextToken().is(tok::kw_inline) && @@ -199,7 +199,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, std::string RBraces; for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i) - RBraces += "} "; + RBraces += "} "; Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition) << FixItHint::CreateReplacement( @@ -216,8 +216,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, // If we're still good, complain about inline namespaces in non-C++0x now. if (InlineLoc.isValid()) - Diag(InlineLoc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_inline_namespace : diag::ext_inline_namespace); + Diag(InlineLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_inline_namespace + : diag::ext_inline_namespace); // Enter a scope for the namespace. ParseScope NamespaceScope(this, Scope::DeclScope); @@ -496,7 +497,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration( if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_directive_declaration) - << 0 /* directive */ << R << FixItHint::CreateRemoval(R); + << 0 /* directive */ << R << FixItHint::CreateRemoval(R); } Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, Attrs); @@ -651,9 +652,9 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, } if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc)) - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 ? - diag::warn_cxx17_compat_using_declaration_pack : - diag::ext_using_declaration_pack); + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 + ? diag::warn_cxx17_compat_using_declaration_pack + : diag::ext_using_declaration_pack); return false; } @@ -766,7 +767,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_directive_declaration) - << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); + << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); // Unfortunately, we have to bail out instead of recovering by // ignoring the parameters, just in case the nested name specifier @@ -811,9 +812,10 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( } if (DeclsInGroup.size() > 1) - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 ? - diag::warn_cxx17_compat_multi_using_declaration : - diag::ext_multi_using_declaration); + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus17 + ? diag::warn_cxx17_compat_multi_using_declaration + : diag::ext_multi_using_declaration); // Eat ';'. DeclEnd = Tok.getLocation(); @@ -835,9 +837,9 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( return nullptr; } - Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_alias_declaration : - diag::ext_alias_declaration); + Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_alias_declaration + : diag::ext_alias_declaration); // Type alias templates cannot be specialized. int SpecKind = -1; @@ -856,7 +858,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( else Range = TemplateInfo.getSourceRange(); Diag(Range.getBegin(), diag::err_alias_declaration_specialization) - << SpecKind << Range; + << SpecKind << Range; SkipUntil(tok::semi); return nullptr; } @@ -869,15 +871,15 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( return nullptr; } else if (D.TypenameLoc.isValid()) Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier) - << FixItHint::CreateRemoval(SourceRange( - D.TypenameLoc, - D.SS.isNotEmpty() ? D.SS.getEndLoc() : D.TypenameLoc)); + << FixItHint::CreateRemoval( + SourceRange(D.TypenameLoc, D.SS.isNotEmpty() ? D.SS.getEndLoc() + : D.TypenameLoc)); else if (D.SS.isNotEmpty()) Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) - << FixItHint::CreateRemoval(D.SS.getRange()); + << FixItHint::CreateRemoval(D.SS.getRange()); if (D.EllipsisLoc.isValid()) Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion) - << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); + << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); Decl *DeclFromDeclSpec = nullptr; TypeResult TypeAlias = @@ -897,8 +899,8 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; MultiTemplateParamsArg TemplateParamsArg( - TemplateParams ? TemplateParams->data() : nullptr, - TemplateParams ? TemplateParams->size() : 0); + TemplateParams ? TemplateParams->data() : nullptr, + TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, UsingLoc, D.Name, Attrs, TypeAlias, DeclFromDeclSpec); @@ -922,10 +924,13 @@ static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr, /// [C11] static_assert-declaration: /// _Static_assert ( constant-expression , string-literal ) ; /// -Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ +Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) { assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) && "Not a static_assert declaration"); + // Save the token used for static assertion. + Token SavedTok = Tok; + if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) Diag(Tok, diag::ext_c11_feature) << Tok.getName(); if (Tok.is(tok::kw_static_assert)) { @@ -974,7 +979,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ if (!isTokenStringLiteral()) { Diag(Tok, diag::err_expected_string_literal) - << /*Source='static_assert'*/1; + << /*Source='static_assert'*/ 1; SkipMalformedDecl(); return nullptr; } @@ -989,10 +994,11 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ T.consumeClose(); DeclEnd = Tok.getLocation(); - ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert); + // Passing the token used to the error message. + ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, + SavedTok.getName()); - return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, - AssertExpr.get(), + return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.get(), AssertMessage.get(), T.getCloseLocation()); } @@ -1003,8 +1009,8 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ /// 'decltype' ( 'auto' ) [C++1y] /// SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { - assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) - && "Not a decltype specifier"); + assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) && + "Not a decltype specifier"); ExprResult Result; SourceLocation StartLoc = Tok.getLocation(); @@ -1028,11 +1034,11 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, - "decltype", tok::r_paren)) { + if (T.expectAndConsume(diag::err_expected_lparen_after, "decltype", + tok::r_paren)) { DS.SetTypeSpecError(); - return T.getOpenLocation() == Tok.getLocation() ? - StartLoc : T.getOpenLocation(); + return T.getOpenLocation() == Tok.getLocation() ? StartLoc + : T.getOpenLocation(); } // Check for C++1y 'decltype(auto)'. @@ -1041,8 +1047,8 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // be 'auto' since C++2b. Diag(Tok.getLocation(), getLangOpts().CPlusPlus14 - ? diag::warn_cxx11_compat_decltype_auto_type_specifier - : diag::ext_decltype_auto_type_specifier); + ? diag::warn_cxx11_compat_decltype_auto_type_specifier + : diag::ext_decltype_auto_type_specifier); ConsumeToken(); } else { // Parse the expression @@ -1100,18 +1106,17 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { unsigned DiagID; const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); // Check for duplicate type specifiers (e.g. "int decltype(a)"). - if (Result.get() - ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, - DiagID, Result.get(), Policy) - : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec, - DiagID, Policy)) { + if (Result.get() ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, + PrevSpec, DiagID, Result.get(), Policy) + : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, + PrevSpec, DiagID, Policy)) { Diag(StartLoc, DiagID) << PrevSpec; DS.SetTypeSpecError(); } return EndLoc; } -void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS, +void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, SourceLocation StartLoc, SourceLocation EndLoc) { // make sure we have a token we can turn into an annotation token @@ -1124,15 +1129,14 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS, // semi-colon. EndLoc = PP.getLastCachedTokenLocation(); } - } - else - PP.EnterToken(Tok, /*IsReinject*/true); + } else + PP.EnterToken(Tok, /*IsReinject*/ true); Tok.setKind(tok::annot_decltype); setExprAnnotation(Tok, - DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() : - DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() : - ExprError()); + DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() + : DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() + : ExprError()); Tok.setAnnotationEndLoc(EndLoc); Tok.setLocation(StartLoc); PP.AnnotateCachedTokens(Tok); @@ -1144,8 +1148,8 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { SourceLocation StartLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, - "__underlying_type", tok::r_paren)) { + if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type", + tok::r_paren)) { return; } @@ -1192,7 +1196,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Ignore attempts to use typename if (Tok.is(tok::kw_typename)) { Diag(Tok, diag::err_expected_class_name_not_template) - << FixItHint::CreateRemoval(Tok.getLocation()); + << FixItHint::CreateRemoval(Tok.getLocation()); ConsumeToken(); } @@ -1211,7 +1215,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) { if (SS.isNotEmpty()) Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype) - << FixItHint::CreateRemoval(SS.getRange()); + << FixItHint::CreateRemoval(SS.getRange()); // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); @@ -1226,7 +1230,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->mightBeType()) { - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TypeResult Type = getTypeAnnotation(Tok); @@ -1253,10 +1257,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // required nor permitted" mode, and do this there. TemplateNameKind TNK = TNK_Non_template; TemplateTy Template; - if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), - &SS, Template, TNK)) { - Diag(IdLoc, diag::err_unknown_template_name) - << Id; + if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), &SS, + Template, TNK)) { + Diag(IdLoc, diag::err_unknown_template_name) << Id; } // Form the template name @@ -1269,7 +1272,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, return true; if (Tok.is(tok::annot_template_id) && takeTemplateIdAnnotation(Tok)->mightBeType()) - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -1332,28 +1335,29 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { // This switch enumerates the valid "follow" set for type-specifiers. switch (Tok.getKind()) { - default: break; - case tok::semi: // struct foo {...} ; - case tok::star: // struct foo {...} * P; - case tok::amp: // struct foo {...} & R = ... - case tok::ampamp: // struct foo {...} && R = ... - case tok::identifier: // struct foo {...} V ; - case tok::r_paren: //(struct foo {...} ) {4} - case tok::coloncolon: // struct foo {...} :: a::b; - case tok::annot_cxxscope: // struct foo {...} a:: b; - case tok::annot_typename: // struct foo {...} a ::b; - case tok::annot_template_id: // struct foo {...} a<int> ::b; - case tok::kw_decltype: // struct foo {...} decltype (a)::b; - case tok::l_paren: // struct foo {...} ( x); - case tok::comma: // __builtin_offsetof(struct foo{...} , - case tok::kw_operator: // struct foo operator ++() {...} - case tok::kw___declspec: // struct foo {...} __declspec(...) - case tok::l_square: // void f(struct f [ 3]) - case tok::ellipsis: // void f(struct f ... [Ns]) + default: + break; + case tok::semi: // struct foo {...} ; + case tok::star: // struct foo {...} * P; + case tok::amp: // struct foo {...} & R = ... + case tok::ampamp: // struct foo {...} && R = ... + case tok::identifier: // struct foo {...} V ; + case tok::r_paren: //(struct foo {...} ) {4} + case tok::coloncolon: // struct foo {...} :: a::b; + case tok::annot_cxxscope: // struct foo {...} a:: b; + case tok::annot_typename: // struct foo {...} a ::b; + case tok::annot_template_id: // struct foo {...} a<int> ::b; + case tok::kw_decltype: // struct foo {...} decltype (a)::b; + case tok::l_paren: // struct foo {...} ( x); + case tok::comma: // __builtin_offsetof(struct foo{...} , + case tok::kw_operator: // struct foo operator ++() {...} + case tok::kw___declspec: // struct foo {...} __declspec(...) + case tok::l_square: // void f(struct f [ 3]) + case tok::ellipsis: // void f(struct f ... [Ns]) // FIXME: we should emit semantic diagnostic when declaration // attribute is in type attribute position. - case tok::kw___attribute: // struct foo __attribute__((used)) x; - case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop)); + case tok::kw___attribute: // struct foo __attribute__((used)) x; + case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop)); // struct foo {...} _Pragma(section(...)); case tok::annot_pragma_ms_pragma: // struct foo {...} _Pragma(vtordisp(pop)); @@ -1362,40 +1366,40 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::annot_pragma_ms_pointers_to_members: return true; case tok::colon: - return CouldBeBitfield || // enum E { ... } : 2; - ColonIsSacred; // _Generic(..., enum E : 2); + return CouldBeBitfield || // enum E { ... } : 2; + ColonIsSacred; // _Generic(..., enum E : 2); // Microsoft compatibility - case tok::kw___cdecl: // struct foo {...} __cdecl x; - case tok::kw___fastcall: // struct foo {...} __fastcall x; - case tok::kw___stdcall: // struct foo {...} __stdcall x; - case tok::kw___thiscall: // struct foo {...} __thiscall x; - case tok::kw___vectorcall: // struct foo {...} __vectorcall x; + case tok::kw___cdecl: // struct foo {...} __cdecl x; + case tok::kw___fastcall: // struct foo {...} __fastcall x; + case tok::kw___stdcall: // struct foo {...} __stdcall x; + case tok::kw___thiscall: // struct foo {...} __thiscall x; + case tok::kw___vectorcall: // struct foo {...} __vectorcall x; // We will diagnose these calling-convention specifiers on non-function // declarations later, so claim they are valid after a type specifier. return getLangOpts().MicrosoftExt; // Type qualifiers - case tok::kw_const: // struct foo {...} const x; - case tok::kw_volatile: // struct foo {...} volatile x; - case tok::kw_restrict: // struct foo {...} restrict x; - case tok::kw__Atomic: // struct foo {...} _Atomic x; - case tok::kw___unaligned: // struct foo {...} __unaligned *x; + case tok::kw_const: // struct foo {...} const x; + case tok::kw_volatile: // struct foo {...} volatile x; + case tok::kw_restrict: // struct foo {...} restrict x; + case tok::kw__Atomic: // struct foo {...} _Atomic x; + case tok::kw___unaligned: // struct foo {...} __unaligned *x; // Function specifiers // Note, no 'explicit'. An explicit function must be either a conversion // operator or a constructor. Either way, it can't have a return type. - case tok::kw_inline: // struct foo inline f(); - case tok::kw_virtual: // struct foo virtual f(); - case tok::kw_friend: // struct foo friend f(); + case tok::kw_inline: // struct foo inline f(); + case tok::kw_virtual: // struct foo virtual f(); + case tok::kw_friend: // struct foo friend f(); // Storage-class specifiers - case tok::kw_static: // struct foo {...} static x; - case tok::kw_extern: // struct foo {...} extern x; - case tok::kw_typedef: // struct foo {...} typedef x; - case tok::kw_register: // struct foo {...} register x; - case tok::kw_auto: // struct foo {...} auto x; - case tok::kw_mutable: // struct foo {...} mutable x; - case tok::kw_thread_local: // struct foo {...} thread_local x; - case tok::kw_constexpr: // struct foo {...} constexpr x; - case tok::kw_consteval: // struct foo {...} consteval x; - case tok::kw_constinit: // struct foo {...} constinit x; + case tok::kw_static: // struct foo {...} static x; + case tok::kw_extern: // struct foo {...} extern x; + case tok::kw_typedef: // struct foo {...} typedef x; + case tok::kw_register: // struct foo {...} register x; + case tok::kw_auto: // struct foo {...} auto x; + case tok::kw_mutable: // struct foo {...} mutable x; + case tok::kw_thread_local: // struct foo {...} thread_local x; + case tok::kw_constexpr: // struct foo {...} constexpr x; + case tok::kw_consteval: // struct foo {...} consteval x; + case tok::kw_constinit: // struct foo {...} constinit x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, // almost no one actually writes code like this. If we see one of these, @@ -1414,7 +1418,7 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { if (!isKnownToBeTypeSpecifier(NextToken())) return true; break; - case tok::r_brace: // struct bar { struct foo {...} } + case tok::r_brace: // struct bar { struct foo {...} } // Missing ';' at end of struct is accepted as an extension in C mode. if (!getLangOpts().CPlusPlus) return true; @@ -1507,8 +1511,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); // Parse inheritance specifiers. - if (Tok.isOneOf(tok::kw___single_inheritance, - tok::kw___multiple_inheritance, + if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance, tok::kw___virtual_inheritance)) ParseMicrosoftInheritanceClassAttributes(attrs); @@ -1519,61 +1522,32 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // C++11 attributes SourceLocation AttrFixitLoc = Tok.getLocation(); - if (TagType == DeclSpec::TST_struct && - Tok.isNot(tok::identifier) && - !Tok.isAnnotation() && - Tok.getIdentifierInfo() && - Tok.isOneOf(tok::kw___is_abstract, - tok::kw___is_aggregate, - tok::kw___is_arithmetic, - tok::kw___is_array, - tok::kw___is_assignable, - tok::kw___is_base_of, - tok::kw___is_class, - tok::kw___is_complete_type, - tok::kw___is_compound, - tok::kw___is_const, - tok::kw___is_constructible, - tok::kw___is_convertible, - tok::kw___is_convertible_to, - tok::kw___is_destructible, - tok::kw___is_empty, - tok::kw___is_enum, - tok::kw___is_floating_point, - tok::kw___is_final, - tok::kw___is_function, - tok::kw___is_fundamental, - tok::kw___is_integral, - tok::kw___is_interface_class, - tok::kw___is_literal, - tok::kw___is_lvalue_expr, - tok::kw___is_lvalue_reference, - tok::kw___is_member_function_pointer, - tok::kw___is_member_object_pointer, - tok::kw___is_member_pointer, - tok::kw___is_nothrow_assignable, - tok::kw___is_nothrow_constructible, - tok::kw___is_nothrow_destructible, - tok::kw___is_object, - tok::kw___is_pod, - tok::kw___is_pointer, - tok::kw___is_polymorphic, - tok::kw___is_reference, - tok::kw___is_rvalue_expr, - tok::kw___is_rvalue_reference, - tok::kw___is_same, - tok::kw___is_scalar, - tok::kw___is_sealed, - tok::kw___is_signed, - tok::kw___is_standard_layout, - tok::kw___is_trivial, - tok::kw___is_trivially_assignable, - tok::kw___is_trivially_constructible, - tok::kw___is_trivially_copyable, - tok::kw___is_union, - tok::kw___is_unsigned, - tok::kw___is_void, - tok::kw___is_volatile)) + if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) && + !Tok.isAnnotation() && Tok.getIdentifierInfo() && + Tok.isOneOf( + tok::kw___is_abstract, tok::kw___is_aggregate, + tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable, + tok::kw___is_base_of, tok::kw___is_class, tok::kw___is_complete_type, + tok::kw___is_compound, tok::kw___is_const, tok::kw___is_constructible, + tok::kw___is_convertible, tok::kw___is_convertible_to, + tok::kw___is_destructible, tok::kw___is_empty, tok::kw___is_enum, + tok::kw___is_floating_point, tok::kw___is_final, + tok::kw___is_function, tok::kw___is_fundamental, + tok::kw___is_integral, tok::kw___is_interface_class, + tok::kw___is_literal, tok::kw___is_lvalue_expr, + tok::kw___is_lvalue_reference, tok::kw___is_member_function_pointer, + tok::kw___is_member_object_pointer, tok::kw___is_member_pointer, + tok::kw___is_nothrow_assignable, tok::kw___is_nothrow_constructible, + tok::kw___is_nothrow_destructible, tok::kw___is_object, + tok::kw___is_pod, tok::kw___is_pointer, tok::kw___is_polymorphic, + tok::kw___is_reference, tok::kw___is_rvalue_expr, + tok::kw___is_rvalue_reference, tok::kw___is_same, tok::kw___is_scalar, + tok::kw___is_sealed, tok::kw___is_signed, + tok::kw___is_standard_layout, tok::kw___is_trivial, + tok::kw___is_trivially_assignable, + tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable, + tok::kw___is_union, tok::kw___is_unsigned, tok::kw___is_void, + tok::kw___is_volatile)) // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 // and Clang. Therefore, when we see the token sequence "struct @@ -1767,7 +1741,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // C++ [class.friend]p2: // A class shall not be defined in a friend declaration. Diag(Tok.getLocation(), diag::err_friend_decl_defines_type) - << SourceRange(DS.getFriendSpecLoc()); + << SourceRange(DS.getFriendSpecLoc()); // Skip everything up to the semicolon, so that this looks like a proper // friend class (or template thereof) declaration. @@ -1821,7 +1795,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // A semicolon was missing after this declaration. Diagnose and recover. ExpectAndConsume(tok::semi, diag::err_expected_after, DeclSpec::getSpecifierName(TagType, PPol)); - PP.EnterToken(Tok, /*IsReinject*/true); + PP.EnterToken(Tok, /*IsReinject*/ true); Tok.setKind(tok::semi); } } else @@ -1838,10 +1812,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, SourceRange AttrRange = Attributes.Range; if (AttrRange.isValid()) { Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) - << AttrRange - << FixItHint::CreateInsertionFromRange(AttrFixitLoc, - CharSourceRange(AttrRange, true)) - << FixItHint::CreateRemoval(AttrRange); + << AttrRange + << FixItHint::CreateInsertionFromRange( + AttrFixitLoc, CharSourceRange(AttrRange, true)) + << FixItHint::CreateRemoval(AttrRange); // Recover by adding misplaced attributes to the attribute list // of the class so they can be applied on the class later. @@ -1849,12 +1823,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } } - if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error || - TUK != Sema::TUK_Definition)) { + if (!Name && !TemplateId && + (DS.getTypeSpecType() == DeclSpec::TST_error || + TUK != Sema::TUK_Definition)) { if (DS.getTypeSpecType() != DeclSpec::TST_error) { // We have a declaration or reference to an anonymous class. Diag(StartLoc, diag::err_anon_type_definition) - << DeclSpec::getSpecifierName(TagType, Policy); + << DeclSpec::getSpecifierName(TagType, Policy); } // If we are parsing a definition and stop at a base-clause, continue on @@ -1869,7 +1844,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Create the tag portion of the class or class template. DeclResult TagOrTempResult = true; // invalid - TypeResult TypeResult = true; // invalid + TypeResult TypeResult = true; // invalid bool Owned = false; Sema::SkipBodyInfo SkipBody; @@ -1881,7 +1856,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TemplateId->isInvalid()) { // Can't build the declaration. } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && - TUK == Sema::TUK_Declaration) { + TUK == Sema::TUK_Declaration) { // This is an explicit instantiation of a class template. ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, /*DiagnoseEmptyAttrs=*/true); @@ -1901,14 +1876,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, /*DiagnoseEmptyAttrs=*/true); - TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc, - SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc); + TypeResult = Actions.ActOnTagTemplateIdType( + TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc, + TemplateId->Template, TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc); } else { // This is an explicit specialization or a class template // partial specialization. @@ -1990,7 +1961,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // If the declarator-id is not a template-id, issue a diagnostic and // recover by ignoring the 'template' keyword. Diag(Tok, diag::err_template_defn_explicit_instantiation) - << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); + << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc); TemplateParams = nullptr; } @@ -2002,7 +1973,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, MultiTemplateParamsArg TParams; if (TUK != Sema::TUK_Reference && TemplateParams) TParams = - MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); + MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size()); stripTypeAttributesOffDeclSpec(attrs, DS, TUK); @@ -2020,8 +1991,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // less common call. if (IsDependent) { assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend); - TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, - SS, Name, StartLoc, NameLoc); + TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, SS, + Name, StartLoc, NameLoc); } } @@ -2071,10 +2042,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec, DiagID, TypeResult.get(), Policy); } else if (!TagOrTempResult.isInvalid()) { - Result = DS.SetTypeSpecType(TagType, StartLoc, - NameLoc.isValid() ? NameLoc : StartLoc, - PrevSpec, DiagID, TagOrTempResult.get(), Owned, - Policy); + Result = DS.SetTypeSpecType( + TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec, + DiagID, TagOrTempResult.get(), Owned, Policy); } else { DS.SetTypeSpecError(); return; @@ -2183,12 +2153,12 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { // Parse the 'virtual' keyword (again!), in case it came after the // access specifier. - if (Tok.is(tok::kw_virtual)) { + if (Tok.is(tok::kw_virtual)) { SourceLocation VirtualLoc = ConsumeToken(); if (IsVirtual) { // Complain about duplicate 'virtual' Diag(VirtualLoc, diag::err_dup_virtual) - << FixItHint::CreateRemoval(VirtualLoc); + << FixItHint::CreateRemoval(VirtualLoc); } IsVirtual = true; @@ -2237,10 +2207,14 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { /// 'public' AccessSpecifier Parser::getAccessSpecifierIfPresent() const { switch (Tok.getKind()) { - default: return AS_none; - case tok::kw_private: return AS_private; - case tok::kw_protected: return AS_protected; - case tok::kw_public: return AS_public; + default: + return AS_none; + case tok::kw_private: + return AS_private; + case tok::kw_protected: + return AS_protected; + case tok::kw_public: + return AS_public; } } @@ -2248,10 +2222,9 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const { /// delayed, e.g., default arguments or an exception-specification, create a /// late-parsed method declaration record to handle the parsing at the end of /// the class definition. -void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, +void Parser::HandleMemberFunctionDeclDelays(Declarator &DeclaratorInfo, Decl *ThisDecl) { - DeclaratorChunk::FunctionTypeInfo &FTI - = DeclaratorInfo.getFunctionTypeInfo(); + DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo(); // If there was a late-parsed exception-specification, we'll need a // late parse bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed; @@ -2348,9 +2321,9 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, if (FriendLoc.isValid()) { Diag(Tok.getLocation(), diag::err_friend_decl_spec) - << VirtSpecifiers::getSpecifierName(Specifier) - << FixItHint::CreateRemoval(Tok.getLocation()) - << SourceRange(FriendLoc, FriendLoc); + << VirtSpecifiers::getSpecifierName(Specifier) + << FixItHint::CreateRemoval(Tok.getLocation()) + << SourceRange(FriendLoc, FriendLoc); ConsumeToken(); continue; } @@ -2360,13 +2333,12 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, const char *PrevSpec = nullptr; if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec)) Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier) - << PrevSpec - << FixItHint::CreateRemoval(Tok.getLocation()); + << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); if (IsInterface && (Specifier == VirtSpecifiers::VS_Final || Specifier == VirtSpecifiers::VS_Sealed)) { Diag(Tok.getLocation(), diag::err_override_control_interface) - << VirtSpecifiers::getSpecifierName(Specifier); + << VirtSpecifiers::getSpecifierName(Specifier); } else if (Specifier == VirtSpecifiers::VS_Sealed) { Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword); } else if (Specifier == VirtSpecifiers::VS_Abstract) { @@ -2436,7 +2408,8 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( VS, getCurrentClass().IsInterface, DeclaratorInfo.getDeclSpec().getFriendSpecLoc()); if (!VS.isUnset()) - MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, + VS); } // If a simple-asm-expr is present, parse it. @@ -2470,7 +2443,8 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) Diag(AL.getLoc(), diag::warn_gcc_attribute_location); - MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, + VS); } } @@ -2487,8 +2461,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( /// Look for declaration specifiers possibly occurring after C++11 /// virt-specifier-seq and diagnose them. void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( - Declarator &D, - VirtSpecifiers &VS) { + Declarator &D, VirtSpecifiers &VS) { DeclSpec DS(AttrFactory); // GNU-style and C++11 attributes are not allowed here, but they will be @@ -2526,15 +2499,15 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( SourceLocation RefQualifierLoc; if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) { const char *Name = (RefQualifierIsLValueRef ? "& " : "&& "); - FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name); + FixItHint Insertion = + FixItHint::CreateInsertion(VS.getFirstLocation(), Name); Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef; Function.RefQualifierLoc = RefQualifierLoc; Diag(RefQualifierLoc, diag::err_declspec_after_virtspec) - << (RefQualifierIsLValueRef ? "&" : "&&") - << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) - << FixItHint::CreateRemoval(RefQualifierLoc) - << Insertion; + << (RefQualifierIsLValueRef ? "&" : "&&") + << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier()) + << FixItHint::CreateRemoval(RefQualifierLoc) << Insertion; D.SetRangeEnd(RefQualifierLoc); } } @@ -2676,10 +2649,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Handle: member-declaration ::= '__extension__' member-declaration if (Tok.is(tok::kw___extension__)) { // __extension__ silences extension warnings in the subexpression. - ExtensionRAIIObject O(Diags); // Use RAII to do this. + ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseCXXClassMemberDeclaration(AS, AccessAttrs, - TemplateInfo, TemplateDiags); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, + TemplateDiags); } ParsedAttributes DeclAttrs(AttrFactory); @@ -2756,9 +2729,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return nullptr; MultiTemplateParamsArg TemplateParams( - TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() - : nullptr, - TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() + : nullptr, + TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0); if (TryConsumeToken(tok::semi)) { if (DS.isFriendSpecified()) @@ -2769,7 +2742,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord); DS.complete(TheDecl); if (AnonRecord) { - Decl* decls[] = {AnonRecord, TheDecl}; + Decl *decls[] = {AnonRecord, TheDecl}; return Actions.BuildDeclaratorGroup(decls); } return Actions.ConvertDeclToDeclGroup(TheDecl); @@ -2787,7 +2760,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation EqualLoc; SourceLocation PureSpecLoc; - auto TryConsumePureSpecifier = [&] (bool AllowDefinition) { + auto TryConsumePureSpecifier = [&](bool AllowDefinition) { if (Tok.isNot(tok::equal)) return false; @@ -2891,9 +2864,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DS.ClearStorageClassSpecs(); } - Decl *FunDecl = - ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, - VS, PureSpecLoc); + Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, + TemplateInfo, VS, PureSpecLoc); if (FunDecl) { for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { @@ -2961,17 +2933,16 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SmallVector<SourceRange, 4> Ranges; DeclaratorInfo.getCXX11AttributeRanges(Ranges); for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); I != E; ++I) + E = Ranges.end(); + I != E; ++I) Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); } else { - ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, - DeclaratorInfo, - TemplateParams, - BitfieldSize.get(), - VS, HasInClassInit); + ThisDecl = Actions.ActOnCXXMemberDeclarator( + getCurScope(), AS, DeclaratorInfo, TemplateParams, BitfieldSize.get(), + VS, HasInClassInit); if (VarTemplateDecl *VT = ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr) @@ -3031,7 +3002,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Actions.ActOnUninitializedDecl(ThisDecl); SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); } else if (ThisDecl) - Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid()); + Actions.AddInitializerToDecl(ThisDecl, Init.get(), + EqualLoc.isInvalid()); } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) // No initializer. Actions.ActOnUninitializedDecl(ThisDecl); @@ -3069,7 +3041,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // the start of a declarator. The comma was probably a typo for a // semicolon. Diag(CommaLoc, diag::err_expected_semi_declaration) - << FixItHint::CreateReplacement(CommaLoc, ";"); + << FixItHint::CreateReplacement(CommaLoc, ";"); ExpectSemi = false; break; } @@ -3127,23 +3099,23 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, /// be a constant-expression. ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc) { - assert(Tok.isOneOf(tok::equal, tok::l_brace) - && "Data member initializer not starting with '=' or '{'"); + assert(Tok.isOneOf(tok::equal, tok::l_brace) && + "Data member initializer not starting with '=' or '{'"); EnterExpressionEvaluationContext Context( Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will - // never type-check. It's better to diagnose it as an ill-formed expression - // than as an ill-formed deleted non-function member. - // An initializer of '= delete p, foo' will never be parsed, because - // a top-level comma always ends the initializer expression. + // never type-check. It's better to diagnose it as an ill-formed + // expression than as an ill-formed deleted non-function member. An + // initializer of '= delete p, foo' will never be parsed, because a + // top-level comma always ends the initializer expression. const Token &Next = NextToken(); if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) { if (IsFunction) Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) - << 1 /* delete */; + << 1 /* delete */; else Diag(ConsumeToken(), diag::err_deleted_non_function); return ExprError(); @@ -3151,7 +3123,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, } else if (Tok.is(tok::kw_default)) { if (IsFunction) Diag(Tok, diag::err_default_delete_in_multiple_declaration) - << 0 /* default */; + << 0 /* default */; else Diag(ConsumeToken(), diag::err_default_special_members) << getLangOpts().CPlusPlus20; @@ -3190,7 +3162,7 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, // within a template argument). if (Tok.is(tok::colon)) { // Enter the scope of the class so that we can correctly parse its bases. - ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); + ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, TagType == DeclSpec::TST_interface); auto OldContext = @@ -3318,8 +3290,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( default: if (tok::isPragmaAnnotation(Tok.getKind())) { Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) - << DeclSpec::getSpecifierName(TagType, - Actions.getASTContext().getPrintingPolicy()); + << DeclSpec::getSpecifierName( + TagType, Actions.getASTContext().getPrintingPolicy()); ConsumeAnnotationToken(); return nullptr; } @@ -3338,9 +3310,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, ParsedAttributes &Attrs, unsigned TagType, Decl *TagDecl) { assert((TagType == DeclSpec::TST_struct || - TagType == DeclSpec::TST_interface || - TagType == DeclSpec::TST_union || - TagType == DeclSpec::TST_class) && "Invalid TagType!"); + TagType == DeclSpec::TST_interface || + TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) && + "Invalid TagType!"); llvm::TimeTraceScope TimeScope("ParseClass", [&]() { if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl)) @@ -3363,10 +3335,10 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // The Microsoft extension __interface does not permit nested classes. if (getCurrentClass().IsInterface) { Diag(RecordLoc, diag::err_invalid_member_in_interface) - << /*ErrorType=*/6 - << (isa<NamedDecl>(TagDecl) - ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString() - : "(anonymous)"); + << /*ErrorType=*/6 + << (isa<NamedDecl>(TagDecl) + ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString() + : "(anonymous)"); } break; } @@ -3379,7 +3351,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } // Enter a scope for the class. - ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); + ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope); // Note that we are parsing a new (potentially-nested) class definition. ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass, @@ -3492,7 +3464,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (SuggestFixIt) { LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {"); // Try recovering from missing { after base-clause. - PP.EnterToken(Tok, /*IsReinject*/true); + PP.EnterToken(Tok, /*IsReinject*/ true); Tok.setKind(tok::l_brace); } else { if (TagDecl) @@ -3586,10 +3558,8 @@ void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) { // FIXME: Suggest where the close brace should have gone by looking // at indentation changes within the definition body. - Diag(D->getLocation(), - diag::err_missing_end_of_definition) << D; - Diag(Tok.getLocation(), - diag::note_missing_end_of_definition_before) << D; + Diag(D->getLocation(), diag::err_missing_end_of_definition) << D; + Diag(Tok.getLocation(), diag::note_missing_end_of_definition_before) << D; // Push '};' onto the token stream to recover. PP.EnterToken(Tok, /*IsReinject*/ true); @@ -3632,7 +3602,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); SourceLocation ColonLoc = ConsumeToken(); - SmallVector<CXXCtorInitializer*, 4> MemInitializers; + SmallVector<CXXCtorInitializer *, 4> MemInitializers; bool AnyErrors = false; do { @@ -3659,12 +3629,12 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { Tok.isOneOf(tok::identifier, tok::coloncolon)) { SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); Diag(Loc, diag::err_ctor_init_missing_comma) - << FixItHint::CreateInsertion(Loc, ", "); + << FixItHint::CreateInsertion(Loc, ", "); } else { // Skip over garbage, until we get to '{'. Don't eat the '{'. if (!MemInit.isInvalid()) - Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace - << tok::comma; + Diag(Tok.getLocation(), diag::err_expected_either) + << tok::l_brace << tok::comma; SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); break; } @@ -3718,7 +3688,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { ? takeTemplateIdAnnotation(Tok) : nullptr; if (TemplateId && TemplateId->mightBeType()) { - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); ConsumeAnnotationToken(); @@ -3745,7 +3715,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy.get(), DS, IdLoc, InitList.get(), EllipsisLoc); - } else if(Tok.is(tok::l_paren)) { + } else if (Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -3779,10 +3749,9 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { if (TemplateTypeTy.isInvalid()) return true; - return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy.get(), DS, IdLoc, - T.getOpenLocation(), ArgExprs, - T.getCloseLocation(), EllipsisLoc); + return Actions.ActOnMemInitializer( + ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy.get(), DS, IdLoc, + T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc); } if (TemplateTypeTy.isInvalid()) @@ -3803,13 +3772,11 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { /// noexcept-specification: /// 'noexcept' /// 'noexcept' '(' constant-expression ')' -ExceptionSpecificationType -Parser::tryParseExceptionSpecification(bool Delayed, - SourceRange &SpecificationRange, - SmallVectorImpl<ParsedType> &DynamicExceptions, - SmallVectorImpl<SourceRange> &DynamicExceptionRanges, - ExprResult &NoexceptExpr, - CachedTokens *&ExceptionSpecTokens) { +ExceptionSpecificationType Parser::tryParseExceptionSpecification( + bool Delayed, SourceRange &SpecificationRange, + SmallVectorImpl<ParsedType> &DynamicExceptions, + SmallVectorImpl<SourceRange> &DynamicExceptionRanges, + ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) { ExceptionSpecificationType Result = EST_None; ExceptionSpecTokens = nullptr; @@ -3838,8 +3805,8 @@ Parser::tryParseExceptionSpecification(bool Delayed, // Cache the tokens for the exception-specification. ExceptionSpecTokens = new CachedTokens; - ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' - ExceptionSpecTokens->push_back(Tok); // '(' + ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' + ExceptionSpecTokens->push_back(Tok); // '(' SpecificationRange.setEnd(ConsumeParen()); // '(' ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, @@ -3852,9 +3819,8 @@ Parser::tryParseExceptionSpecification(bool Delayed, // See if there's a dynamic specification. if (Tok.is(tok::kw_throw)) { - Result = ParseDynamicExceptionSpecification(SpecificationRange, - DynamicExceptions, - DynamicExceptionRanges); + Result = ParseDynamicExceptionSpecification( + SpecificationRange, DynamicExceptions, DynamicExceptionRanges); assert(DynamicExceptions.size() == DynamicExceptionRanges.size() && "Produced different number of exception types and ranges."); } @@ -3878,8 +3844,8 @@ Parser::tryParseExceptionSpecification(bool Delayed, NoexceptExpr = ParseConstantExpression(); T.consumeClose(); if (!NoexceptExpr.isInvalid()) { - NoexceptExpr = Actions.ActOnNoexceptSpec(NoexceptExpr.get(), - NoexceptType); + NoexceptExpr = + Actions.ActOnNoexceptSpec(NoexceptExpr.get(), NoexceptType); NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { NoexceptType = EST_BasicNoexcept; @@ -3908,17 +3874,16 @@ Parser::tryParseExceptionSpecification(bool Delayed, return Result; } -static void diagnoseDynamicExceptionSpecification( - Parser &P, SourceRange Range, bool IsNoexcept) { +static void diagnoseDynamicExceptionSpecification(Parser &P, SourceRange Range, + bool IsNoexcept) { if (P.getLangOpts().CPlusPlus11) { const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)"; - P.Diag(Range.getBegin(), - P.getLangOpts().CPlusPlus17 && !IsNoexcept - ? diag::ext_dynamic_exception_spec - : diag::warn_exception_spec_deprecated) + P.Diag(Range.getBegin(), P.getLangOpts().CPlusPlus17 && !IsNoexcept + ? diag::ext_dynamic_exception_spec + : diag::warn_exception_spec_deprecated) << Range; P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated) - << Replacement << FixItHint::CreateReplacement(Range, Replacement); + << Replacement << FixItHint::CreateReplacement(Range, Replacement); } } @@ -3934,9 +3899,8 @@ static void diagnoseDynamicExceptionSpecification( /// type-id-list ',' type-id ... [opt] /// ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( - SourceRange &SpecificationRange, - SmallVectorImpl<ParsedType> &Exceptions, - SmallVectorImpl<SourceRange> &Ranges) { + SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &Exceptions, + SmallVectorImpl<SourceRange> &Ranges) { assert(Tok.is(tok::kw_throw) && "expected throw"); SpecificationRange.setBegin(ConsumeToken()); @@ -4010,10 +3974,9 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) { SourceLocation RequiresKWLoc = ConsumeToken(); ExprResult TrailingRequiresClause; - ParseScope ParamScope(this, - Scope::DeclScope | - Scope::FunctionDeclarationScope | - Scope::FunctionPrototypeScope); + ParseScope ParamScope(this, Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); @@ -4063,9 +4026,9 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) { /// We have just started parsing the definition of a new class, /// so push that class onto our stack of classes that is currently /// being parsed. -Sema::ParsingClassState -Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass, - bool IsInterface) { +Sema::ParsingClassState Parser::PushParsingClass(Decl *ClassDecl, + bool NonNestedClass, + bool IsInterface) { assert((NonNestedClass || !ClassStack.empty()) && "Nested class without outer class"); ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface)); @@ -4113,7 +4076,8 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { // This nested class has some members that will need to be processed // after the top-level class is completely defined. Therefore, add // it to the list of nested classes within its parent. - assert(getCurScope()->isClassScope() && "Nested class outside of class scope?"); + assert(getCurScope()->isClassScope() && + "Nested class outside of class scope?"); ClassStack.top()->LateParsedDeclarations.push_back( new LateParsedClass(this, Victim)); } @@ -4295,13 +4259,10 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, /// '[' balanced-token-seq ']' /// '{' balanced-token-seq '}' /// any token but '(', ')', '[', ']', '{', or '}' -bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - CachedTokens &OpenMPTokens) { +bool Parser::ParseCXX11AttributeArgs( + IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, CachedTokens &OpenMPTokens) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); const LangOptions &LO = getLangOpts(); @@ -4321,7 +4282,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, !hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX11 : AttributeCommonInfo::Syntax::AS_C2x, ScopeName, AttrName, getTargetInfo(), getLangOpts())) { - if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) {} + if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) { + } // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); @@ -4339,7 +4301,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, if (ScopeName && ScopeName->isStr("omp")) { Diag(AttrNameLoc, getLangOpts().OpenMP >= 51 ? diag::warn_omp51_compat_attributes - : diag::ext_omp_attributes); + : diag::ext_omp_attributes); ParseOpenMPAttributeArgs(AttrName, OpenMPTokens); @@ -4354,9 +4316,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); else - NumArgs = - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); + NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); if (!Attrs.empty() && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { @@ -4444,7 +4405,7 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, Diag(Tok.getLocation(), diag::err_expected) << tok::colon; } - llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs; + llvm::SmallDenseMap<IdentifierInfo *, SourceLocation, 4> SeenAttrs; bool AttrParsed = false; while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) { @@ -4510,8 +4471,7 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, } if (TryConsumeToken(tok::ellipsis)) - Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) - << AttrName; + Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) << AttrName; } // If we hit an error and recovered by parsing up to a semicolon, eat the @@ -4556,8 +4516,7 @@ void Parser::DiagnoseAndSkipCXX11Attributes() { if (EndLoc.isValid()) { SourceRange Range(StartLoc, EndLoc); - Diag(StartLoc, diag::err_attributes_not_allowed) - << Range; + Diag(StartLoc, diag::err_attributes_not_allowed) << Range; } } @@ -4756,7 +4715,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( case IEB_Dependent: Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) - << Result.IsIfExists; + << Result.IsIfExists; // Fall through to skip. LLVM_FALLTHROUGH; @@ -4768,8 +4727,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration(TagType, - AccessAttrs, CurAS); + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS); continue; } diff --git a/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp index 6ca98876b8fc..74fa70379858 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParsePragma.cpp @@ -350,6 +350,16 @@ struct PragmaMaxTokensTotalHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaRISCVHandler : public PragmaHandler { + PragmaRISCVHandler(Sema &Actions) + : PragmaHandler("riscv"), Actions(Actions) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override; + +private: + Sema &Actions; +}; + void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) { for (auto &T : Toks) T.setFlag(clang::Token::IsReinjected); @@ -493,6 +503,11 @@ void Parser::initializePragmaHandlers() { MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>(); PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); + + if (getTargetInfo().getTriple().isRISCV()) { + RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions); + PP.AddPragmaHandler("clang", RISCVPragmaHandler.get()); + } } void Parser::resetPragmaHandlers() { @@ -617,6 +632,11 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get()); MaxTokensTotalPragmaHandler.reset(); + + if (getTargetInfo().getTriple().isRISCV()) { + PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get()); + RISCVPragmaHandler.reset(); + } } /// Handle the annotation token produced for #pragma unused(...) @@ -3929,3 +3949,35 @@ void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP, PP.overrideMaxTokens(MaxTokens, Loc); } + +// Handle '#pragma clang riscv intrinsic vector'. +void PragmaRISCVHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducer Introducer, + Token &FirstToken) { + Token Tok; + PP.Lex(Tok); + IdentifierInfo *II = Tok.getIdentifierInfo(); + + if (!II || !II->isStr("intrinsic")) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) + << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'"; + return; + } + + PP.Lex(Tok); + II = Tok.getIdentifierInfo(); + if (!II || !II->isStr("vector")) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) + << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'"; + return; + } + + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "clang riscv intrinsic"; + return; + } + + Actions.DeclareRISCVVBuiltins = true; +} diff --git a/contrib/llvm-project/clang/lib/Parse/Parser.cpp b/contrib/llvm-project/clang/lib/Parse/Parser.cpp index ab8748c2c63d..fd044660845b 100644 --- a/contrib/llvm-project/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm-project/clang/lib/Parse/Parser.cpp @@ -153,7 +153,7 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, return true; } -bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { +bool Parser::ExpectAndConsumeSemi(unsigned DiagID, StringRef TokenUsed) { if (TryConsumeToken(tok::semi)) return false; @@ -172,7 +172,7 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { return false; } - return ExpectAndConsume(tok::semi, DiagID); + return ExpectAndConsume(tok::semi, DiagID , TokenUsed); } void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, DeclSpec::TST TST) { diff --git a/contrib/llvm-project/clang/lib/Sema/Scope.cpp b/contrib/llvm-project/clang/lib/Sema/Scope.cpp index 499279a2659d..98260226dfd3 100644 --- a/contrib/llvm-project/clang/lib/Sema/Scope.cpp +++ b/contrib/llvm-project/clang/lib/Sema/Scope.cpp @@ -91,7 +91,7 @@ void Scope::Init(Scope *parent, unsigned flags) { UsingDirectives.clear(); Entity = nullptr; ErrorTrap.reset(); - NRVO.setPointerAndInt(nullptr, false); + NRVO = None; } bool Scope::containedInPrototypeScope() const { @@ -118,19 +118,71 @@ void Scope::AddFlags(unsigned FlagsToSet) { Flags |= FlagsToSet; } -void Scope::mergeNRVOIntoParent() { - if (VarDecl *Candidate = NRVO.getPointer()) { - if (isDeclScope(Candidate)) - Candidate->setNRVOVariable(true); +// The algorithm for updating NRVO candidate is as follows: +// 1. All previous candidates become invalid because a new NRVO candidate is +// obtained. Therefore, we need to clear return slots for other +// variables defined before the current return statement in the current +// scope and in outer scopes. +// 2. Store the new candidate if its return slot is available. Otherwise, +// there is no NRVO candidate so far. +void Scope::updateNRVOCandidate(VarDecl *VD) { + auto UpdateReturnSlotsInScopeForVD = [VD](Scope *S) -> bool { + bool IsReturnSlotFound = S->ReturnSlots.contains(VD); + + // We found a candidate variable that can be put into a return slot. + // Clear the set, because other variables cannot occupy a return + // slot in the same scope. + S->ReturnSlots.clear(); + + if (IsReturnSlotFound) + S->ReturnSlots.insert(VD); + + return IsReturnSlotFound; + }; + + bool CanBePutInReturnSlot = false; + + for (auto *S = this; S; S = S->getParent()) { + CanBePutInReturnSlot |= UpdateReturnSlotsInScopeForVD(S); + + if (S->getEntity()) + break; } - if (getEntity()) + // Consider the variable as NRVO candidate if the return slot is available + // for it in the current scope, or if it can be available in outer scopes. + NRVO = CanBePutInReturnSlot ? VD : nullptr; +} + +void Scope::applyNRVO() { + // There is no NRVO candidate in the current scope. + if (!NRVO.hasValue()) return; - if (NRVO.getInt()) - getParent()->setNoNRVO(); - else if (NRVO.getPointer()) - getParent()->addNRVOCandidate(NRVO.getPointer()); + if (*NRVO && isDeclScope(*NRVO)) + NRVO.getValue()->setNRVOVariable(true); + + // It's necessary to propagate NRVO candidate to the parent scope for cases + // when the parent scope doesn't contain a return statement. + // For example: + // X foo(bool b) { + // X x; + // if (b) + // return x; + // exit(0); + // } + // Also, we need to propagate nullptr value that means NRVO is not + // allowed in this scope. + // For example: + // X foo(bool b) { + // X x; + // if (b) + // return x; + // else + // return X(); // NRVO is not allowed + // } + if (!getEntity()) + getParent()->NRVO = *NRVO; } LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } @@ -193,8 +245,10 @@ void Scope::dumpImpl(raw_ostream &OS) const { if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; - if (NRVO.getInt()) - OS << "NRVO not allowed\n"; - else if (NRVO.getPointer()) - OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; + if (!NRVO) + OS << "there is no NRVO candidate\n"; + else if (*NRVO) + OS << "NRVO candidate : (clang::VarDecl*)" << *NRVO << '\n'; + else + OS << "NRVO is not allowed\n"; } diff --git a/contrib/llvm-project/clang/lib/Sema/Sema.cpp b/contrib/llvm-project/clang/lib/Sema/Sema.cpp index 326010d4d93f..08957ce9fada 100644 --- a/contrib/llvm-project/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm-project/clang/lib/Sema/Sema.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/MultiplexExternalSemaSource.h" #include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaConsumer.h" @@ -137,9 +138,9 @@ public: void reset() { S = nullptr; } - virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override { + void FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) override { if (!S) return; switch (Reason) { diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp index 8d2fc5331a0d..985005d0b79b 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp @@ -2092,7 +2092,7 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { - S->mergeNRVOIntoParent(); + S->applyNRVO(); if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && @@ -18899,14 +18899,24 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, const llvm::APSInt &InitVal = ECD->getInitVal(); // Keep track of the size of positive and negative values. - if (InitVal.isUnsigned() || InitVal.isNonNegative()) - NumPositiveBits = std::max(NumPositiveBits, - (unsigned)InitVal.getActiveBits()); - else + if (InitVal.isUnsigned() || InitVal.isNonNegative()) { + // If the enumerator is zero that should still be counted as a positive + // bit since we need a bit to store the value zero. + unsigned ActiveBits = InitVal.getActiveBits(); + NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); + } else { NumNegativeBits = std::max(NumNegativeBits, (unsigned)InitVal.getMinSignedBits()); + } } + // If we have have an empty set of enumerators we still need one bit. + // From [dcl.enum]p8 + // If the enumerator-list is empty, the values of the enumeration are as if + // the enumeration had a single enumerator with value 0 + if (!NumPositiveBits && !NumNegativeBits) + NumPositiveBits = 1; + // Figure out the type that should be used for this enum. QualType BestType; unsigned BestWidth; diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp index cd5cdbde7f3f..0f79978b0911 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp @@ -13824,7 +13824,8 @@ static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr, // C99 6.5.16.1 QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, - QualType CompoundType) { + QualType CompoundType, + BinaryOperatorKind Opc) { assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject)); // Verify that LHS is a modifiable lvalue, and emit error if not. @@ -13937,10 +13938,18 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // expression or an unevaluated operand ExprEvalContexts.back().VolatileAssignmentLHSs.push_back(LHSExpr); } else { - // C++2a [expr.ass]p6: + // C++20 [expr.ass]p6: // [Compound-assignment] expressions are deprecated if E1 has - // volatile-qualified type - Diag(Loc, diag::warn_deprecated_compound_assign_volatile) << LHSType; + // volatile-qualified type and op is not one of the bitwise + // operators |, &, ˆ. + switch (Opc) { + case BO_OrAssign: + case BO_AndAssign: + case BO_XorAssign: + break; + default: + Diag(Loc, diag::warn_deprecated_compound_assign_volatile) << LHSType; + } } } @@ -14879,7 +14888,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, switch (Opc) { case BO_Assign: - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType()); + ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType(), Opc); if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = LHS.get()->getValueKind(); @@ -14976,32 +14985,37 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, Opc == BO_DivAssign); CompLHSTy = CompResultTy; if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_RemAssign: CompResultTy = CheckRemainderOperands(LHS, RHS, OpLoc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_AddAssign: ConvertHalfVec = true; CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy); if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_SubAssign: ConvertHalfVec = true; CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy); if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_ShlAssign: case BO_ShrAssign: CompResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_AndAssign: case BO_OrAssign: // fallthrough @@ -15011,7 +15025,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc); CompLHSTy = CompResultTy; if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid()) - ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy); + ResultTy = + CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy, Opc); break; case BO_Comma: ResultTy = CheckCommaOperands(*this, LHS, RHS, OpLoc); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp index 242e1f81d75c..68158ec977cf 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp @@ -29,6 +29,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" +#include "clang/Sema/RISCVIntrinsicManager.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" @@ -928,6 +929,14 @@ bool Sema::LookupBuiltin(LookupResult &R) { } } + if (DeclareRISCVVBuiltins) { + if (!RVIntrinsicManager) + RVIntrinsicManager = CreateRISCVIntrinsicManager(*this); + + if (RVIntrinsicManager->CreateIntrinsicIfFound(R, II, PP)) + return true; + } + // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { // In C++, C2x, and OpenCL (spec v1.2 s6.9.f), we don't have any @@ -3838,6 +3847,12 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, // associated classes are visible within their respective // namespaces even if they are not visible during an ordinary // lookup (11.4). + // + // C++20 [basic.lookup.argdep] p4.3 + // -- are exported, are attached to a named module M, do not appear + // in the translation unit containing the point of the lookup, and + // have the same innermost enclosing non-inline namespace scope as + // a declaration of an associated entity attached to M. DeclContext::lookup_result R = NS->lookup(Name); for (auto *D : R) { auto *Underlying = D; @@ -3858,6 +3873,36 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, if (isVisible(D)) { Visible = true; break; + } else if (getLangOpts().CPlusPlusModules && + D->isInExportDeclContext()) { + // C++20 [basic.lookup.argdep] p4.3 .. are exported ... + Module *FM = D->getOwningModule(); + // exports are only valid in module purview and outside of any + // PMF (although a PMF should not even be present in a module + // with an import). + assert(FM && FM->isModulePurview() && !FM->isPrivateModule() && + "bad export context"); + // .. are attached to a named module M, do not appear in the + // translation unit containing the point of the lookup.. + if (!isModuleUnitOfCurrentTU(FM) && + llvm::any_of(AssociatedClasses, [&](auto *E) { + // ... and have the same innermost enclosing non-inline + // namespace scope as a declaration of an associated entity + // attached to M + if (!E->hasOwningModule() || + E->getOwningModule()->getTopLevelModuleName() != + FM->getTopLevelModuleName()) + return false; + // TODO: maybe this could be cached when generating the + // associated namespaces / entities. + DeclContext *Ctx = E->getDeclContext(); + while (!Ctx->isFileContext() || Ctx->isInlineNamespace()) + Ctx = Ctx->getParent(); + return Ctx == NS; + })) { + Visible = true; + break; + } } } else if (D->getFriendObjectKind()) { auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext()); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm-project/clang/lib/Sema/SemaOverload.cpp index c226ed625479..d72cc33ed0f5 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaOverload.cpp @@ -63,8 +63,9 @@ static ExprResult CreateFunctionRefExpr( // being used. if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc)) return ExprError(); - DeclRefExpr *DRE = new (S.Context) - DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); + DeclRefExpr *DRE = + DeclRefExpr::Create(S.Context, Fn->getQualifierLoc(), SourceLocation(), + Fn, false, Loc, Fn->getType(), VK_LValue, FoundDecl); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); @@ -6400,6 +6401,27 @@ void Sema::AddOverloadCandidate( return; } + // Functions with internal linkage are only viable in the same module unit. + if (auto *MF = Function->getOwningModule()) { + if (getLangOpts().CPlusPlusModules && !MF->isModuleMapModule() && + !isModuleUnitOfCurrentTU(MF)) { + /// FIXME: Currently, the semantics of linkage in clang is slightly + /// different from the semantics in C++ spec. In C++ spec, only names + /// have linkage. So that all entities of the same should share one + /// linkage. But in clang, different entities of the same could have + /// different linkage. + NamedDecl *ND = Function; + if (auto *SpecInfo = Function->getTemplateSpecializationInfo()) + ND = SpecInfo->getTemplate(); + + if (ND->getFormalLinkage() == Linkage::InternalLinkage) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_module_mismatched; + return; + } + } + } + if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() && !Function->getAttr<TargetAttr>()->isDefaultVersion()) { Candidate.Viable = false; diff --git a/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp new file mode 100644 index 000000000000..50fd841c231b --- /dev/null +++ b/contrib/llvm-project/clang/lib/Sema/SemaRISCVVectorLookup.cpp @@ -0,0 +1,395 @@ +//==- SemaRISCVVectorLookup.cpp - Name Lookup for RISC-V Vector Intrinsic -==// +// +// 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 implements name lookup for RISC-V vector intrinsic. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/RISCVIntrinsicManager.h" +#include "clang/Sema/Sema.h" +#include "clang/Support/RISCVVIntrinsicUtils.h" +#include "llvm/ADT/SmallVector.h" +#include <string> +#include <vector> + +using namespace llvm; +using namespace clang; +using namespace clang::RISCV; + +namespace { + +// Function definition of a RVV intrinsic. +struct RVVIntrinsicDef { + /// Full function name with suffix, e.g. vadd_vv_i32m1. + std::string Name; + + /// Overloaded function name, e.g. vadd. + std::string OverloadName; + + /// Mapping to which clang built-in function, e.g. __builtin_rvv_vadd. + std::string BuiltinName; + + /// Function signature, first element is return type. + RVVTypes Signature; +}; + +struct RVVOverloadIntrinsicDef { + // Indexes of RISCVIntrinsicManagerImpl::IntrinsicList. + SmallVector<size_t, 8> Indexes; +}; + +} // namespace + +static const PrototypeDescriptor RVVSignatureTable[] = { +#define DECL_SIGNATURE_TABLE +#include "clang/Basic/riscv_vector_builtin_sema.inc" +#undef DECL_SIGNATURE_TABLE +}; + +static const RVVIntrinsicRecord RVVIntrinsicRecords[] = { +#define DECL_INTRINSIC_RECORDS +#include "clang/Basic/riscv_vector_builtin_sema.inc" +#undef DECL_INTRINSIC_RECORDS +}; + +// Get subsequence of signature table. +static ArrayRef<PrototypeDescriptor> ProtoSeq2ArrayRef(uint16_t Index, + uint8_t Length) { + return makeArrayRef(&RVVSignatureTable[Index], Length); +} + +static QualType RVVType2Qual(ASTContext &Context, const RVVType *Type) { + QualType QT; + switch (Type->getScalarType()) { + case ScalarTypeKind::Void: + QT = Context.VoidTy; + break; + case ScalarTypeKind::Size_t: + QT = Context.getSizeType(); + break; + case ScalarTypeKind::Ptrdiff_t: + QT = Context.getPointerDiffType(); + break; + case ScalarTypeKind::UnsignedLong: + QT = Context.UnsignedLongTy; + break; + case ScalarTypeKind::SignedLong: + QT = Context.LongTy; + break; + case ScalarTypeKind::Boolean: + QT = Context.BoolTy; + break; + case ScalarTypeKind::SignedInteger: + QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), true); + break; + case ScalarTypeKind::UnsignedInteger: + QT = Context.getIntTypeForBitwidth(Type->getElementBitwidth(), false); + break; + case ScalarTypeKind::Float: + switch (Type->getElementBitwidth()) { + case 64: + QT = Context.DoubleTy; + break; + case 32: + QT = Context.FloatTy; + break; + case 16: + QT = Context.Float16Ty; + break; + default: + llvm_unreachable("Unsupported floating point width."); + } + break; + case Invalid: + llvm_unreachable("Unhandled type."); + } + if (Type->isVector()) + QT = Context.getScalableVectorType(QT, Type->getScale().getValue()); + + if (Type->isConstant()) + QT = Context.getConstType(QT); + + // Transform the type to a pointer as the last step, if necessary. + if (Type->isPointer()) + QT = Context.getPointerType(QT); + + return QT; +} + +namespace { +class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { +private: + Sema &S; + ASTContext &Context; + + // List of all RVV intrinsic. + std::vector<RVVIntrinsicDef> IntrinsicList; + // Mapping function name to index of IntrinsicList. + StringMap<size_t> Intrinsics; + // Mapping function name to RVVOverloadIntrinsicDef. + StringMap<RVVOverloadIntrinsicDef> OverloadIntrinsics; + + // Create IntrinsicList + void InitIntrinsicList(); + + // Create RVVIntrinsicDef. + void InitRVVIntrinsic(const RVVIntrinsicRecord &Record, StringRef SuffixStr, + StringRef OverloadedSuffixStr, bool IsMask, + RVVTypes &Types); + + // Create FunctionDecl for a vector intrinsic. + void CreateRVVIntrinsicDecl(LookupResult &LR, IdentifierInfo *II, + Preprocessor &PP, unsigned Index, + bool IsOverload); + +public: + RISCVIntrinsicManagerImpl(clang::Sema &S) : S(S), Context(S.Context) { + InitIntrinsicList(); + } + + // Create RISC-V vector intrinsic and insert into symbol table if found, and + // return true, otherwise return false. + bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II, + Preprocessor &PP) override; +}; +} // namespace + +void RISCVIntrinsicManagerImpl::InitIntrinsicList() { + const TargetInfo &TI = Context.getTargetInfo(); + bool HasVectorFloat32 = TI.hasFeature("zve32f"); + bool HasVectorFloat64 = TI.hasFeature("zve64d"); + bool HasZvfh = TI.hasFeature("experimental-zvfh"); + bool HasRV64 = TI.hasFeature("64bit"); + bool HasFullMultiply = TI.hasFeature("v"); + + // Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics + // in RISCVVEmitter.cpp. + for (auto &Record : RVVIntrinsicRecords) { + // Create Intrinsics for each type and LMUL. + BasicType BaseType = BasicType::Unknown; + ArrayRef<PrototypeDescriptor> BasicProtoSeq = + ProtoSeq2ArrayRef(Record.PrototypeIndex, Record.PrototypeLength); + ArrayRef<PrototypeDescriptor> SuffixProto = + ProtoSeq2ArrayRef(Record.SuffixIndex, Record.SuffixLength); + ArrayRef<PrototypeDescriptor> OverloadedSuffixProto = ProtoSeq2ArrayRef( + Record.OverloadedSuffixIndex, Record.OverloadedSuffixSize); + + llvm::SmallVector<PrototypeDescriptor> ProtoSeq = + RVVIntrinsic::computeBuiltinTypes(BasicProtoSeq, /*IsMasked=*/false, + /*HasMaskedOffOperand=*/false, + Record.HasVL, Record.NF); + + llvm::SmallVector<PrototypeDescriptor> ProtoMaskSeq = + RVVIntrinsic::computeBuiltinTypes(BasicProtoSeq, /*IsMasked=*/true, + Record.HasMaskedOffOperand, + Record.HasVL, Record.NF); + + for (unsigned int TypeRangeMaskShift = 0; + TypeRangeMaskShift <= static_cast<unsigned int>(BasicType::MaxOffset); + ++TypeRangeMaskShift) { + unsigned int BaseTypeI = 1 << TypeRangeMaskShift; + BaseType = static_cast<BasicType>(BaseTypeI); + + if ((BaseTypeI & Record.TypeRangeMask) != BaseTypeI) + continue; + + // Check requirement. + if (BaseType == BasicType::Float16 && !HasZvfh) + continue; + + if (BaseType == BasicType::Float32 && !HasVectorFloat32) + continue; + + if (BaseType == BasicType::Float64 && !HasVectorFloat64) + continue; + + if (((Record.RequiredExtensions & RVV_REQ_RV64) == RVV_REQ_RV64) && + !HasRV64) + continue; + + if ((BaseType == BasicType::Int64) && + ((Record.RequiredExtensions & RVV_REQ_FullMultiply) == + RVV_REQ_FullMultiply) && + !HasFullMultiply) + continue; + + // Expanded with different LMUL. + for (int Log2LMUL = -3; Log2LMUL <= 3; Log2LMUL++) { + if (!(Record.Log2LMULMask & (1 << (Log2LMUL + 3)))) + continue; + + Optional<RVVTypes> Types = + RVVType::computeTypes(BaseType, Log2LMUL, Record.NF, ProtoSeq); + + // Ignored to create new intrinsic if there are any illegal types. + if (!Types.hasValue()) + continue; + + std::string SuffixStr = + RVVIntrinsic::getSuffixStr(BaseType, Log2LMUL, SuffixProto); + std::string OverloadedSuffixStr = RVVIntrinsic::getSuffixStr( + BaseType, Log2LMUL, OverloadedSuffixProto); + + // Create non-masked intrinsic. + InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, false, *Types); + + if (Record.HasMasked) { + // Create masked intrinsic. + Optional<RVVTypes> MaskTypes = RVVType::computeTypes( + BaseType, Log2LMUL, Record.NF, ProtoMaskSeq); + + InitRVVIntrinsic(Record, SuffixStr, OverloadedSuffixStr, true, + *MaskTypes); + } + } + } + } +} + +// Compute name and signatures for intrinsic with practical types. +void RISCVIntrinsicManagerImpl::InitRVVIntrinsic( + const RVVIntrinsicRecord &Record, StringRef SuffixStr, + StringRef OverloadedSuffixStr, bool IsMask, RVVTypes &Signature) { + // Function name, e.g. vadd_vv_i32m1. + std::string Name = Record.Name; + if (!SuffixStr.empty()) + Name += "_" + SuffixStr.str(); + + if (IsMask) + Name += "_m"; + + // Overloaded function name, e.g. vadd. + std::string OverloadedName; + if (!Record.OverloadedName) + OverloadedName = StringRef(Record.Name).split("_").first.str(); + else + OverloadedName = Record.OverloadedName; + if (!OverloadedSuffixStr.empty()) + OverloadedName += "_" + OverloadedSuffixStr.str(); + + // clang built-in function name, e.g. __builtin_rvv_vadd. + std::string BuiltinName = "__builtin_rvv_" + std::string(Record.Name); + if (IsMask) + BuiltinName += "_m"; + + // Put into IntrinsicList. + size_t Index = IntrinsicList.size(); + IntrinsicList.push_back({Name, OverloadedName, BuiltinName, Signature}); + + // Creating mapping to Intrinsics. + Intrinsics.insert({Name, Index}); + + // Get the RVVOverloadIntrinsicDef. + RVVOverloadIntrinsicDef &OverloadIntrinsicDef = + OverloadIntrinsics[OverloadedName]; + + // And added the index. + OverloadIntrinsicDef.Indexes.push_back(Index); +} + +void RISCVIntrinsicManagerImpl::CreateRVVIntrinsicDecl(LookupResult &LR, + IdentifierInfo *II, + Preprocessor &PP, + unsigned Index, + bool IsOverload) { + ASTContext &Context = S.Context; + RVVIntrinsicDef &IDef = IntrinsicList[Index]; + RVVTypes Sigs = IDef.Signature; + size_t SigLength = Sigs.size(); + RVVType *ReturnType = Sigs[0]; + QualType RetType = RVVType2Qual(Context, ReturnType); + SmallVector<QualType, 8> ArgTypes; + QualType BuiltinFuncType; + + // Skip return type, and convert RVVType to QualType for arguments. + for (size_t i = 1; i < SigLength; ++i) + ArgTypes.push_back(RVVType2Qual(Context, Sigs[i])); + + FunctionProtoType::ExtProtoInfo PI( + Context.getDefaultCallingConvention(false, false, true)); + + PI.Variadic = false; + + SourceLocation Loc = LR.getNameLoc(); + BuiltinFuncType = Context.getFunctionType(RetType, ArgTypes, PI); + DeclContext *Parent = Context.getTranslationUnitDecl(); + + FunctionDecl *RVVIntrinsicDecl = FunctionDecl::Create( + Context, Parent, Loc, Loc, II, BuiltinFuncType, /*TInfo=*/nullptr, + SC_Extern, S.getCurFPFeatures().isFPConstrained(), + /*isInlineSpecified*/ false, + /*hasWrittenPrototype*/ true); + + // Create Decl objects for each parameter, adding them to the + // FunctionDecl. + const auto *FP = cast<FunctionProtoType>(BuiltinFuncType); + SmallVector<ParmVarDecl *, 8> ParmList; + for (unsigned IParm = 0, E = FP->getNumParams(); IParm != E; ++IParm) { + ParmVarDecl *Parm = + ParmVarDecl::Create(Context, RVVIntrinsicDecl, Loc, Loc, nullptr, + FP->getParamType(IParm), nullptr, SC_None, nullptr); + Parm->setScopeInfo(0, IParm); + ParmList.push_back(Parm); + } + RVVIntrinsicDecl->setParams(ParmList); + + // Add function attributes. + if (IsOverload) + RVVIntrinsicDecl->addAttr(OverloadableAttr::CreateImplicit(Context)); + + // Setup alias to __builtin_rvv_* + IdentifierInfo &IntrinsicII = PP.getIdentifierTable().get(IDef.BuiltinName); + RVVIntrinsicDecl->addAttr( + BuiltinAliasAttr::CreateImplicit(S.Context, &IntrinsicII)); + + // Add to symbol table. + LR.addDecl(RVVIntrinsicDecl); +} + +bool RISCVIntrinsicManagerImpl::CreateIntrinsicIfFound(LookupResult &LR, + IdentifierInfo *II, + Preprocessor &PP) { + StringRef Name = II->getName(); + + // Lookup the function name from the overload intrinsics first. + auto OvIItr = OverloadIntrinsics.find(Name); + if (OvIItr != OverloadIntrinsics.end()) { + const RVVOverloadIntrinsicDef &OvIntrinsicDef = OvIItr->second; + for (auto Index : OvIntrinsicDef.Indexes) + CreateRVVIntrinsicDecl(LR, II, PP, Index, + /*IsOverload*/ true); + + // If we added overloads, need to resolve the lookup result. + LR.resolveKind(); + return true; + } + + // Lookup the function name from the intrinsics. + auto Itr = Intrinsics.find(Name); + if (Itr != Intrinsics.end()) { + CreateRVVIntrinsicDecl(LR, II, PP, Itr->second, + /*IsOverload*/ false); + return true; + } + + // It's not an RVV intrinsics. + return false; +} + +namespace clang { +std::unique_ptr<clang::sema::RISCVIntrinsicManager> +CreateRISCVIntrinsicManager(Sema &S) { + return std::make_unique<RISCVIntrinsicManagerImpl>(S); +} +} // namespace clang diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index f25694ce48c9..c6ca10c0342c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -3898,12 +3898,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, if (R.isInvalid() || ExprEvalContexts.back().isDiscardedStatementContext()) return R; - if (VarDecl *VD = - const_cast<VarDecl*>(cast<ReturnStmt>(R.get())->getNRVOCandidate())) { - CurScope->addNRVOCandidate(VD); - } else { - CurScope->setNoNRVO(); - } + VarDecl *VD = + const_cast<VarDecl *>(cast<ReturnStmt>(R.get())->getNRVOCandidate()); + + CurScope->updateNRVOCandidate(VD); CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp index 95c83ebfaeab..1542a07713fb 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp @@ -20,6 +20,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/Stack.h" @@ -8707,23 +8708,59 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, // Check for conflicting previous declaration. DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, - ForVisibleRedeclaration); + forRedeclarationInCurContext()); LookupName(Previous, S); - FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false, /*AllowInlineNamespace*/false); - if (!Previous.empty()) { - auto *Old = Previous.getRepresentativeDecl(); - Diag(NameLoc, isa<ConceptDecl>(Old) ? diag::err_redefinition : - diag::err_redefinition_different_kind) << NewDecl->getDeclName(); - Diag(Old->getLocation(), diag::note_previous_definition); - } + bool AddToScope = true; + CheckConceptRedefinition(NewDecl, Previous, AddToScope); ActOnDocumentableDecl(NewDecl); - PushOnScopeChains(NewDecl, S); + if (AddToScope) + PushOnScopeChains(NewDecl, S); return NewDecl; } +void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, + LookupResult &Previous, bool &AddToScope) { + AddToScope = true; + + if (Previous.empty()) + return; + + auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()); + if (!OldConcept) { + auto *Old = Previous.getRepresentativeDecl(); + Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind) + << NewDecl->getDeclName(); + notePreviousDefinition(Old, NewDecl->getLocation()); + AddToScope = false; + return; + } + // Check if we can merge with a concept declaration. + bool IsSame = Context.isSameEntity(NewDecl, OldConcept); + if (!IsSame) { + Diag(NewDecl->getLocation(), diag::err_redefinition_different_concept) + << NewDecl->getDeclName(); + notePreviousDefinition(OldConcept, NewDecl->getLocation()); + AddToScope = false; + return; + } + if (hasReachableDefinition(OldConcept)) { + Diag(NewDecl->getLocation(), diag::err_redefinition) + << NewDecl->getDeclName(); + notePreviousDefinition(OldConcept, NewDecl->getLocation()); + AddToScope = false; + return; + } + if (!Previous.isSingleResult()) { + // FIXME: we should produce an error in case of ambig and failed lookups. + // Other decls (e.g. namespaces) also have this shortcoming. + return; + } + Context.setPrimaryMergedDecl(NewDecl, OldConcept); +} + /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index d70e824224df..73800191dfc1 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2926,7 +2926,8 @@ Attr *ASTRecordReader::readAttr() { /// Reads attributes from the current stream position. void ASTRecordReader::readAttributes(AttrVec &Attrs) { for (unsigned I = 0, E = readInt(); I != E; ++I) - Attrs.push_back(readAttr()); + if (auto *A = readAttr()) + Attrs.push_back(A); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp index fac8fc141d2c..0739dcc1ce60 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp @@ -4347,8 +4347,12 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef, void ASTRecordWriter::AddAttr(const Attr *A) { auto &Record = *this; - if (!A) + // FIXME: Clang can't handle the serialization/deserialization of + // preferred_name properly now. See + // https://github.com/llvm/llvm-project/issues/56490 for example. + if (!A || (isa<PreferredNameAttr>(A) && Writer->isWritingNamedModules())) return Record.push_back(0); + Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs Record.AddIdentifierRef(A->getAttrName()); diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 987cf65d6fec..9a6c013bcf66 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -26,9 +26,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" +#include <functional> using namespace clang; using namespace ento; +using namespace std::placeholders; namespace { struct AnyArgExpr { @@ -118,10 +120,14 @@ public: const LocationContext *LCtx, const CallEvent *Call) const; - typedef void (CStringChecker::*FnCheck)(CheckerContext &, - const CallExpr *) const; + using FnCheck = std::function<void(const CStringChecker *, CheckerContext &, + const CallExpr *)>; + CallDescriptionMap<FnCheck> Callbacks = { - {{CDF_MaybeBuiltin, "memcpy", 3}, &CStringChecker::evalMemcpy}, + {{CDF_MaybeBuiltin, "memcpy", 3}, + std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, false)}, + {{CDF_MaybeBuiltin, "wmemcpy", 3}, + std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, true)}, {{CDF_MaybeBuiltin, "mempcpy", 3}, &CStringChecker::evalMempcpy}, {{CDF_MaybeBuiltin, "memcmp", 3}, &CStringChecker::evalMemcmp}, {{CDF_MaybeBuiltin, "memmove", 3}, &CStringChecker::evalMemmove}, @@ -135,7 +141,9 @@ public: {{CDF_MaybeBuiltin, "strncat", 3}, &CStringChecker::evalStrncat}, {{CDF_MaybeBuiltin, "strlcat", 3}, &CStringChecker::evalStrlcat}, {{CDF_MaybeBuiltin, "strlen", 1}, &CStringChecker::evalstrLength}, + {{CDF_MaybeBuiltin, "wcslen", 1}, &CStringChecker::evalstrLength}, {{CDF_MaybeBuiltin, "strnlen", 2}, &CStringChecker::evalstrnLength}, + {{CDF_MaybeBuiltin, "wcsnlen", 2}, &CStringChecker::evalstrnLength}, {{CDF_MaybeBuiltin, "strcmp", 2}, &CStringChecker::evalStrcmp}, {{CDF_MaybeBuiltin, "strncmp", 3}, &CStringChecker::evalStrncmp}, {{CDF_MaybeBuiltin, "strcasecmp", 2}, &CStringChecker::evalStrcasecmp}, @@ -152,14 +160,14 @@ public: StdCopyBackward{{"std", "copy_backward"}, 3}; FnCheck identifyCall(const CallEvent &Call, CheckerContext &C) const; - void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; + void evalMemcpy(CheckerContext &C, const CallExpr *CE, bool IsWide) const; void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; void evalMemmove(CheckerContext &C, const CallExpr *CE) const; void evalBcopy(CheckerContext &C, const CallExpr *CE) const; void evalCopyCommon(CheckerContext &C, const CallExpr *CE, ProgramStateRef state, SizeArgExpr Size, DestinationArgExpr Dest, SourceArgExpr Source, - bool Restricted, bool IsMempcpy) const; + bool Restricted, bool IsMempcpy, bool IsWide) const; void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; @@ -240,13 +248,14 @@ public: AnyArgExpr Arg, SVal l) const; ProgramStateRef CheckLocation(CheckerContext &C, ProgramStateRef state, AnyArgExpr Buffer, SVal Element, - AccessKind Access) const; + AccessKind Access, bool IsWide = false) const; ProgramStateRef CheckBufferAccess(CheckerContext &C, ProgramStateRef State, AnyArgExpr Buffer, SizeArgExpr Size, - AccessKind Access) const; + AccessKind Access, + bool IsWide = false) const; ProgramStateRef CheckOverlap(CheckerContext &C, ProgramStateRef state, SizeArgExpr Size, AnyArgExpr First, - AnyArgExpr Second) const; + AnyArgExpr Second, bool IsWide = false) const; void emitOverlapBug(CheckerContext &C, ProgramStateRef state, const Stmt *First, @@ -329,7 +338,8 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C, ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, ProgramStateRef state, AnyArgExpr Buffer, SVal Element, - AccessKind Access) const { + AccessKind Access, + bool IsWide) const { // If a previous check has failed, propagate the failure. if (!state) @@ -344,17 +354,36 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, if (!ER) return state; - if (ER->getValueType() != C.getASTContext().CharTy) - return state; + SValBuilder &svalBuilder = C.getSValBuilder(); + ASTContext &Ctx = svalBuilder.getContext(); + + // Get the index of the accessed element. + NonLoc Idx = ER->getIndex(); + + if (!IsWide) { + if (ER->getValueType() != Ctx.CharTy) + return state; + } else { + if (ER->getValueType() != Ctx.WideCharTy) + return state; + + QualType SizeTy = Ctx.getSizeType(); + NonLoc WideSize = + svalBuilder + .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(), + SizeTy) + .castAs<NonLoc>(); + SVal Offset = svalBuilder.evalBinOpNN(state, BO_Mul, Idx, WideSize, SizeTy); + if (Offset.isUnknown()) + return state; + Idx = Offset.castAs<NonLoc>(); + } // Get the size of the array. const auto *superReg = cast<SubRegion>(ER->getSuperRegion()); DefinedOrUnknownSVal Size = getDynamicExtent(state, superReg, C.getSValBuilder()); - // Get the index of the accessed element. - DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); - ProgramStateRef StInBound, StOutBound; std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, Size); if (StOutBound && !StInBound) { @@ -385,11 +414,10 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, return StInBound; } -ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, - ProgramStateRef State, - AnyArgExpr Buffer, - SizeArgExpr Size, - AccessKind Access) const { +ProgramStateRef +CStringChecker::CheckBufferAccess(CheckerContext &C, ProgramStateRef State, + AnyArgExpr Buffer, SizeArgExpr Size, + AccessKind Access, bool IsWide) const { // If a previous check has failed, propagate the failure. if (!State) return nullptr; @@ -398,7 +426,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, ASTContext &Ctx = svalBuilder.getContext(); QualType SizeTy = Size.Expression->getType(); - QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); + QualType PtrTy = Ctx.getPointerType(IsWide ? Ctx.WideCharTy : Ctx.CharTy); // Check that the first buffer is non-null. SVal BufVal = C.getSVal(Buffer.Expression); @@ -432,7 +460,7 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, SVal BufEnd = svalBuilder.evalBinOpLN(State, BO_Add, *BufLoc, LastOffset, PtrTy); - State = CheckLocation(C, State, Buffer, BufEnd, Access); + State = CheckLocation(C, State, Buffer, BufEnd, Access, IsWide); // If the buffer isn't large enough, abort. if (!State) @@ -446,7 +474,8 @@ ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C, ProgramStateRef state, SizeArgExpr Size, AnyArgExpr First, - AnyArgExpr Second) const { + AnyArgExpr Second, + bool IsWide) const { if (!Filter.CheckCStringBufferOverlap) return state; @@ -525,7 +554,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C, // Convert the first buffer's start address to char*. // Bail out if the cast fails. ASTContext &Ctx = svalBuilder.getContext(); - QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); + QualType CharPtrTy = Ctx.getPointerType(IsWide ? Ctx.WideCharTy : Ctx.CharTy); SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, First.Expression->getType()); Optional<Loc> FirstStartLoc = FirstStart.getAs<Loc>(); @@ -1161,7 +1190,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallExpr *CE, ProgramStateRef state, SizeArgExpr Size, DestinationArgExpr Dest, SourceArgExpr Source, bool Restricted, - bool IsMempcpy) const { + bool IsMempcpy, bool IsWide) const { CurrentFunctionDescription = "memory copy function"; // See if the size argument is zero. @@ -1204,11 +1233,11 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallExpr *CE, return; // Ensure the accesses are valid and that the buffers do not overlap. - state = CheckBufferAccess(C, state, Dest, Size, AccessKind::write); - state = CheckBufferAccess(C, state, Source, Size, AccessKind::read); + state = CheckBufferAccess(C, state, Dest, Size, AccessKind::write, IsWide); + state = CheckBufferAccess(C, state, Source, Size, AccessKind::read, IsWide); if (Restricted) - state = CheckOverlap(C, state, Size, Dest, Source); + state = CheckOverlap(C, state, Size, Dest, Source, IsWide); if (!state) return; @@ -1258,7 +1287,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallExpr *CE, } } -void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { +void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE, + bool IsWide) const { // void *memcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is the address of the destination buffer. DestinationArgExpr Dest = {CE->getArg(0), 0}; @@ -1269,7 +1299,8 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { constexpr bool IsRestricted = true; constexpr bool IsMempcpy = false; - evalCopyCommon(C, CE, State, Size, Dest, Src, IsRestricted, IsMempcpy); + evalCopyCommon(C, CE, State, Size, Dest, Src, IsRestricted, IsMempcpy, + IsWide); } void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { @@ -1281,7 +1312,8 @@ void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { constexpr bool IsRestricted = true; constexpr bool IsMempcpy = true; - evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy); + evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy, + false); } void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { @@ -1293,7 +1325,8 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { constexpr bool IsRestricted = false; constexpr bool IsMempcpy = false; - evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy); + evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy, + false); } void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { @@ -1304,7 +1337,8 @@ void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { constexpr bool IsRestricted = false; constexpr bool IsMempcpy = false; - evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy); + evalCopyCommon(C, CE, C.getState(), Size, Dest, Src, IsRestricted, IsMempcpy, + false); } void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { @@ -2336,7 +2370,7 @@ bool CStringChecker::evalCall(const CallEvent &Call, CheckerContext &C) const { // Check and evaluate the call. const auto *CE = cast<CallExpr>(Call.getOriginExpr()); - (this->*Callback)(C, CE); + Callback(this, C, CE); // If the evaluate call resulted in no change, chain to the next eval call // handler. diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp index 895212d134b8..b673b51c4623 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp @@ -55,9 +55,9 @@ public: ID.AddPointer(getTag()); } - virtual PathDiagnosticPieceRef - VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - PathSensitiveBugReport &BR) override; + PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) override; // FIXME: Scan the map once in the visitor's constructor and do a direct // lookup by region. diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 36464707d06a..adedc9c30fad 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -852,9 +852,8 @@ protected: return false; } - virtual bool - wasModifiedInFunction(const ExplodedNode *CallEnterN, - const ExplodedNode *CallExitEndN) override { + bool wasModifiedInFunction(const ExplodedNode *CallEnterN, + const ExplodedNode *CallExitEndN) override { if (!doesFnIntendToHandleOwnership( CallExitEndN->getFirstPred()->getLocationContext()->getDecl(), CallExitEndN->getState()->getAnalysisManager().getASTContext())) @@ -885,7 +884,7 @@ protected: "later deallocation"); } - virtual PathDiagnosticPieceRef + PathDiagnosticPieceRef maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R, const ObjCMethodCall &Call, const ExplodedNode *N) override { @@ -893,7 +892,7 @@ protected: return nullptr; } - virtual PathDiagnosticPieceRef + PathDiagnosticPieceRef maybeEmitNoteForCXXThis(PathSensitiveBugReport &R, const CXXConstructorCall &Call, const ExplodedNode *N) override { @@ -901,7 +900,7 @@ protected: return nullptr; } - virtual PathDiagnosticPieceRef + PathDiagnosticPieceRef maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N) override { // TODO: Factor the logic of "what constitutes as an entity being passed diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index cddf206728b1..27fd40a441fa 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -182,7 +182,7 @@ public: return false; }; - if (std::any_of(RD->field_begin(), RD->field_end(), IsTrickyField)) + if (llvm::any_of(RD->fields(), IsTrickyField)) return true; return false; } diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index ef673ae41a3d..5897e5096461 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -240,7 +240,7 @@ class StdLibraryFunctionsChecker ArgNo OtherArgN; public: - virtual StringRef getName() const override { return "Comparison"; }; + StringRef getName() const override { return "Comparison"; }; ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode, ArgNo OtherArgN) : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {} diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index 38e69e81d800..cd91fa9b090c 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -57,19 +57,17 @@ class RegularField final : public FieldNode { public: RegularField(const FieldRegion *FR) : FieldNode(FR) {} - virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + void printNoteMsg(llvm::raw_ostream &Out) const override { Out << "uninitialized field "; } - virtual void printPrefix(llvm::raw_ostream &Out) const override {} + void printPrefix(llvm::raw_ostream &Out) const override {} - virtual void printNode(llvm::raw_ostream &Out) const override { + void printNode(llvm::raw_ostream &Out) const override { Out << getVariableName(getDecl()); } - virtual void printSeparator(llvm::raw_ostream &Out) const override { - Out << '.'; - } + void printSeparator(llvm::raw_ostream &Out) const override { Out << '.'; } }; /// Represents that the FieldNode that comes after this is declared in a base @@ -85,20 +83,20 @@ public: assert(T->getAsCXXRecordDecl()); } - virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + void printNoteMsg(llvm::raw_ostream &Out) const override { llvm_unreachable("This node can never be the final node in the " "fieldchain!"); } - virtual void printPrefix(llvm::raw_ostream &Out) const override {} + void printPrefix(llvm::raw_ostream &Out) const override {} - virtual void printNode(llvm::raw_ostream &Out) const override { + void printNode(llvm::raw_ostream &Out) const override { Out << BaseClassT->getAsCXXRecordDecl()->getName() << "::"; } - virtual void printSeparator(llvm::raw_ostream &Out) const override {} + void printSeparator(llvm::raw_ostream &Out) const override {} - virtual bool isBase() const override { return true; } + bool isBase() const override { return true; } }; } // end of anonymous namespace diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp index a6e81b3657a2..f5bd765ff679 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -34,20 +34,20 @@ public: LocField(const FieldRegion *FR, const bool IsDereferenced = true) : FieldNode(FR), IsDereferenced(IsDereferenced) {} - virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + void printNoteMsg(llvm::raw_ostream &Out) const override { if (IsDereferenced) Out << "uninitialized pointee "; else Out << "uninitialized pointer "; } - virtual void printPrefix(llvm::raw_ostream &Out) const override {} + void printPrefix(llvm::raw_ostream &Out) const override {} - virtual void printNode(llvm::raw_ostream &Out) const override { + void printNode(llvm::raw_ostream &Out) const override { Out << getVariableName(getDecl()); } - virtual void printSeparator(llvm::raw_ostream &Out) const override { + void printSeparator(llvm::raw_ostream &Out) const override { if (getDecl()->getType()->isPointerType()) Out << "->"; else @@ -64,11 +64,11 @@ public: NeedsCastLocField(const FieldRegion *FR, const QualType &T) : FieldNode(FR), CastBackType(T) {} - virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + void printNoteMsg(llvm::raw_ostream &Out) const override { Out << "uninitialized pointee "; } - virtual void printPrefix(llvm::raw_ostream &Out) const override { + void printPrefix(llvm::raw_ostream &Out) const override { // If this object is a nonloc::LocAsInteger. if (getDecl()->getType()->isIntegerType()) Out << "reinterpret_cast"; @@ -78,13 +78,11 @@ public: Out << '<' << CastBackType.getAsString() << ">("; } - virtual void printNode(llvm::raw_ostream &Out) const override { + void printNode(llvm::raw_ostream &Out) const override { Out << getVariableName(getDecl()) << ')'; } - virtual void printSeparator(llvm::raw_ostream &Out) const override { - Out << "->"; - } + void printSeparator(llvm::raw_ostream &Out) const override { Out << "->"; } }; /// Represents a Loc field that points to itself. @@ -93,17 +91,17 @@ class CyclicLocField final : public FieldNode { public: CyclicLocField(const FieldRegion *FR) : FieldNode(FR) {} - virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + void printNoteMsg(llvm::raw_ostream &Out) const override { Out << "object references itself "; } - virtual void printPrefix(llvm::raw_ostream &Out) const override {} + void printPrefix(llvm::raw_ostream &Out) const override {} - virtual void printNode(llvm::raw_ostream &Out) const override { + void printNode(llvm::raw_ostream &Out) const override { Out << getVariableName(getDecl()); } - virtual void printSeparator(llvm::raw_ostream &Out) const override { + void printSeparator(llvm::raw_ostream &Out) const override { llvm_unreachable("CyclicLocField objects must be the last node of the " "fieldchain!"); } diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 2caa5bbc16df..3a90c37a36da 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -530,9 +530,8 @@ public: private: /// \return Whether \c RegionOfInterest was modified at \p CurrN compared to /// the value it holds in \p CallExitBeginN. - virtual bool - wasModifiedBeforeCallExit(const ExplodedNode *CurrN, - const ExplodedNode *CallExitBeginN) override; + bool wasModifiedBeforeCallExit(const ExplodedNode *CurrN, + const ExplodedNode *CallExitBeginN) override; /// Attempts to find the region of interest in a given record decl, /// by either following the base classes or fields. @@ -547,19 +546,17 @@ private: // Region of interest corresponds to an IVar, exiting a method // which could have written into that IVar, but did not. - virtual PathDiagnosticPieceRef - maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R, - const ObjCMethodCall &Call, - const ExplodedNode *N) override final; + PathDiagnosticPieceRef maybeEmitNoteForObjCSelf(PathSensitiveBugReport &R, + const ObjCMethodCall &Call, + const ExplodedNode *N) final; - virtual PathDiagnosticPieceRef - maybeEmitNoteForCXXThis(PathSensitiveBugReport &R, - const CXXConstructorCall &Call, - const ExplodedNode *N) override final; + PathDiagnosticPieceRef maybeEmitNoteForCXXThis(PathSensitiveBugReport &R, + const CXXConstructorCall &Call, + const ExplodedNode *N) final; - virtual PathDiagnosticPieceRef + PathDiagnosticPieceRef maybeEmitNoteForParameters(PathSensitiveBugReport &R, const CallEvent &Call, - const ExplodedNode *N) override final; + const ExplodedNode *N) final; /// Consume the information on the no-store stack frame in order to /// either emit a note or suppress the report enirely. diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index d8f56f2f8cff..19149d079822 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -196,6 +196,14 @@ typedef llvm::ImmutableMap< IndexOfElementToConstructMap; REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) + +// This trait is responsible for holding our pending ArrayInitLoopExprs. +// It pairs the LocationContext and the initializer CXXConstructExpr with +// the size of the array that's being copy initialized. +typedef llvm::ImmutableMap< + std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned> + PendingInitLoopMap; +REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingInitLoop, PendingInitLoopMap) //===----------------------------------------------------------------------===// // Engine construction and deletion. //===----------------------------------------------------------------------===// @@ -462,6 +470,34 @@ ProgramStateRef ExprEngine::setIndexOfElementToConstruct( return State->set<IndexOfElementToConstruct>(Key, Idx); } +Optional<unsigned> ExprEngine::getPendingInitLoop(ProgramStateRef State, + const CXXConstructExpr *E, + const LocationContext *LCtx) { + + return Optional<unsigned>::create( + State->get<PendingInitLoop>({E, LCtx->getStackFrame()})); +} + +ProgramStateRef ExprEngine::removePendingInitLoop(ProgramStateRef State, + const CXXConstructExpr *E, + const LocationContext *LCtx) { + auto Key = std::make_pair(E, LCtx->getStackFrame()); + + assert(E && State->contains<PendingInitLoop>(Key)); + return State->remove<PendingInitLoop>(Key); +} + +ProgramStateRef ExprEngine::setPendingInitLoop(ProgramStateRef State, + const CXXConstructExpr *E, + const LocationContext *LCtx, + unsigned Size) { + auto Key = std::make_pair(E, LCtx->getStackFrame()); + + assert(!State->contains<PendingInitLoop>(Key) && Size > 0); + + return State->set<PendingInitLoop>(Key, Size); +} + Optional<unsigned> ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, @@ -487,17 +523,23 @@ ExprEngine::addObjectUnderConstruction(ProgramStateRef State, const LocationContext *LC, SVal V) { ConstructedObjectKey Key(Item, LC->getStackFrame()); - const CXXConstructExpr *E = nullptr; + const Expr *Init = nullptr; if (auto DS = dyn_cast_or_null<DeclStmt>(Item.getStmtOrNull())) { if (auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) - E = dyn_cast<CXXConstructExpr>(VD->getInit()); + Init = VD->getInit(); } - if (!E && !Item.getStmtOrNull()) { - auto CtorInit = Item.getCXXCtorInitializer(); - E = dyn_cast<CXXConstructExpr>(CtorInit->getInit()); - } + if (auto LE = dyn_cast_or_null<LambdaExpr>(Item.getStmtOrNull())) + Init = *(LE->capture_init_begin() + Item.getIndex()); + + if (!Init && !Item.getStmtOrNull()) + Init = Item.getCXXCtorInitializer()->getInit(); + + // In an ArrayInitLoopExpr the real initializer is returned by + // getSubExpr(). + if (const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init)) + Init = AILE->getSubExpr(); // FIXME: Currently the state might already contain the marker due to // incorrect handling of temporaries bound to default parameters. @@ -508,7 +550,8 @@ ExprEngine::addObjectUnderConstruction(ProgramStateRef State, assert((!State->get<ObjectsUnderConstruction>(Key) || Key.getItem().getKind() == ConstructionContextItem::TemporaryDestructorKind || - State->contains<IndexOfElementToConstruct>({E, LC})) && + State->contains<IndexOfElementToConstruct>( + {dyn_cast_or_null<CXXConstructExpr>(Init), LC})) && "The object is already marked as `UnderConstruction`, when it's not " "supposed to!"); return State->set<ObjectsUnderConstruction>(Key, V); @@ -2744,7 +2787,10 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, SVal Base = state->getLValue(DD, LCtx); if (DD->getType()->isReferenceType()) { - Base = state->getSVal(Base.getAsRegion()); + if (const MemRegion *R = Base.getAsRegion()) + Base = state->getSVal(R); + else + Base = UnknownVal(); } SVal V = UnknownVal(); @@ -2765,15 +2811,27 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, V = state->getLValue(BD->getType(), Idx, Base); } - // Handle binding to tuple-like strcutures - else if (BD->getHoldingVar()) { - // FIXME: handle tuples - return; + // Handle binding to tuple-like structures + else if (const auto *HV = BD->getHoldingVar()) { + V = state->getLValue(HV, LCtx); + + if (HV->getType()->isReferenceType()) { + if (const MemRegion *R = V.getAsRegion()) + V = state->getSVal(R); + else + V = UnknownVal(); + } } else llvm_unreachable("An unknown case of structured binding encountered!"); - if (BD->getType()->isReferenceType()) - V = state->getSVal(V.getAsRegion()); + // In case of tuple-like types the references are already handled, so we + // don't want to handle them again. + if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) { + if (const MemRegion *R = V.getAsRegion()) + V = state->getSVal(R); + else + V = UnknownVal(); + } Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr, ProgramPoint::PostLValueKind); @@ -2797,6 +2855,11 @@ void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, const Expr *Arr = Ex->getCommonExpr()->getSourceExpr(); for (auto *Node : CheckerPreStmt) { + + // The constructor visitior has already taken care of everything. + if (auto *CE = dyn_cast<CXXConstructExpr>(Ex->getSubExpr())) + break; + const LocationContext *LCtx = Node->getLocationContext(); ProgramStateRef state = Node->getState(); diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 08fac9fb2e69..04e00274b2a7 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -290,6 +290,23 @@ SVal ExprEngine::computeObjectUnderConstruction( return loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(E, LCtx)); } + case ConstructionContext::LambdaCaptureKind: { + CallOpts.IsTemporaryCtorOrDtor = true; + + const auto *LCC = cast<LambdaCaptureConstructionContext>(CC); + + SVal Base = loc::MemRegionVal( + MRMgr.getCXXTempObjectRegion(LCC->getInitializer(), LCtx)); + + const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E); + if (getIndexOfElementToConstruct(State, CE, LCtx)) { + CallOpts.IsArrayCtorOrDtor = true; + Base = State->getLValue(E->getType(), svalBuilder.makeArrayIndex(Idx), + Base); + } + + return Base; + } case ConstructionContext::ArgumentKind: { // Arguments are technically temporaries. CallOpts.IsTemporaryCtorOrDtor = true; @@ -450,6 +467,17 @@ ProgramStateRef ExprEngine::updateObjectsUnderConstruction( return State; } + case ConstructionContext::LambdaCaptureKind: { + const auto *LCC = cast<LambdaCaptureConstructionContext>(CC); + + // If we capture and array, we want to store the super region, not a + // sub-region. + if (const auto *EL = dyn_cast_or_null<ElementRegion>(V.getAsRegion())) + V = loc::MemRegionVal(EL->getSuperRegion()); + + return addObjectUnderConstruction( + State, {LCC->getLambdaExpr(), LCC->getIndex()}, LCtx, V); + } case ConstructionContext::ArgumentKind: { const auto *ACC = cast<ArgumentConstructionContext>(CC); if (const auto *BTE = ACC->getCXXBindTemporaryExpr()) @@ -462,6 +490,59 @@ ProgramStateRef ExprEngine::updateObjectsUnderConstruction( llvm_unreachable("Unhandled construction context!"); } +static ProgramStateRef +bindRequiredArrayElementToEnvironment(ProgramStateRef State, + const ArrayInitLoopExpr *AILE, + const LocationContext *LCtx, SVal Idx) { + // The ctor in this case is guaranteed to be a copy ctor, otherwise we hit a + // compile time error. + // + // -ArrayInitLoopExpr <-- we're here + // |-OpaqueValueExpr + // | `-DeclRefExpr <-- match this + // `-CXXConstructExpr + // `-ImplicitCastExpr + // `-ArraySubscriptExpr + // |-ImplicitCastExpr + // | `-OpaqueValueExpr + // | `-DeclRefExpr + // `-ArrayInitIndexExpr + // + // The resulting expression might look like the one below in an implicit + // copy/move ctor. + // + // ArrayInitLoopExpr <-- we're here + // |-OpaqueValueExpr + // | `-MemberExpr <-- match this + // | (`-CXXStaticCastExpr) <-- move ctor only + // | `-DeclRefExpr + // `-CXXConstructExpr + // `-ArraySubscriptExpr + // |-ImplicitCastExpr + // | `-OpaqueValueExpr + // | `-MemberExpr + // | `-DeclRefExpr + // `-ArrayInitIndexExpr + // + // HACK: There is no way we can put the index of the array element into the + // CFG unless we unroll the loop, so we manually select and bind the required + // parameter to the environment. + const auto *CE = cast<CXXConstructExpr>(AILE->getSubExpr()); + const auto *OVESrc = AILE->getCommonExpr()->getSourceExpr(); + + SVal Base = UnknownVal(); + if (const auto *ME = dyn_cast<MemberExpr>(OVESrc)) + Base = State->getSVal(ME, LCtx); + else if (const auto *DRE = cast<DeclRefExpr>(OVESrc)) + Base = State->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx); + else + llvm_unreachable("ArrayInitLoopExpr contains unexpected source expression"); + + SVal NthElem = State->getLValue(CE->getType(), Idx, Base); + + return State->BindExpr(CE->getArg(0), LCtx, NthElem); +} + void ExprEngine::handleConstructor(const Expr *E, ExplodedNode *Pred, ExplodedNodeSet &destNodes) { @@ -502,12 +583,26 @@ void ExprEngine::handleConstructor(const Expr *E, // Inherited constructors are always base class constructors. assert(CE && !CIE && "A complete constructor is inherited?!"); + // If the ctor is part of an ArrayInitLoopExpr, we want to handle it + // differently. + auto *AILE = CC ? CC->getArrayInitLoop() : nullptr; + unsigned Idx = 0; - if (CE->getType()->isArrayType()) { + if (CE->getType()->isArrayType() || AILE) { Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u); State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1); } + if (AILE) { + // Only set this once even though we loop through it multiple times. + if (!getPendingInitLoop(State, CE, LCtx)) + State = setPendingInitLoop(State, CE, LCtx, + AILE->getArraySize().getLimitedValue()); + + State = bindRequiredArrayElementToEnvironment( + State, AILE, LCtx, svalBuilder.makeArrayIndex(Idx)); + } + // The target region is found from construction context. std::tie(State, Target) = handleConstructionContext(CE, State, LCtx, CC, CallOpts, Idx); @@ -908,7 +1003,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // values are properly placed inside the required region, however if an // initializer list is used, this doesn't happen automatically. auto *Init = CNE->getInitializer(); - bool isInitList = dyn_cast_or_null<InitListExpr>(Init); + bool isInitList = isa_and_nonnull<InitListExpr>(Init); QualType ObjTy = isInitList ? Init->getType() : CNE->getType()->getPointeeType(); @@ -1038,19 +1133,40 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, // If we created a new MemRegion for the lambda, we should explicitly bind // the captures. + unsigned Idx = 0; CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin(); for (LambdaExpr::const_capture_init_iterator i = LE->capture_init_begin(), e = LE->capture_init_end(); - i != e; ++i, ++CurField) { + i != e; ++i, ++CurField, ++Idx) { FieldDecl *FieldForCapture = *CurField; SVal FieldLoc = State->getLValue(FieldForCapture, V); SVal InitVal; if (!FieldForCapture->hasCapturedVLAType()) { Expr *InitExpr = *i; + + if (const auto AILE = dyn_cast<ArrayInitLoopExpr>(InitExpr)) { + // If the AILE initializes a POD array, we need to keep it as the + // InitExpr. + if (dyn_cast<CXXConstructExpr>(AILE->getSubExpr())) + InitExpr = AILE->getSubExpr(); + } + assert(InitExpr && "Capture missing initialization expression"); - InitVal = State->getSVal(InitExpr, LocCtxt); + + if (dyn_cast<CXXConstructExpr>(InitExpr)) { + InitVal = *getObjectUnderConstruction(State, {LE, Idx}, LocCtxt); + InitVal = State->getSVal(InitVal.getAsRegion()); + + State = finishObjectConstruction(State, {LE, Idx}, LocCtxt); + } else + InitVal = State->getSVal(InitExpr, LocCtxt); + } else { + + assert(!getObjectUnderConstruction(State, {LE, Idx}, LocCtxt) && + "VLA capture by value is a compile time error!"); + // The field stores the length of a captured variable-length array. // These captures don't have initialization expressions; instead we // get the length from the VLAType size expression. diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index ebcca92a3e4e..8fb2ce9cd18f 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -265,9 +265,13 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { ShouldRepeatCall = shouldRepeatCtorCall(state, CCE, callerCtx); - if (!ShouldRepeatCall && - getIndexOfElementToConstruct(state, CCE, callerCtx)) - state = removeIndexOfElementToConstruct(state, CCE, callerCtx); + if (!ShouldRepeatCall) { + if (getIndexOfElementToConstruct(state, CCE, callerCtx)) + state = removeIndexOfElementToConstruct(state, CCE, callerCtx); + + if (getPendingInitLoop(state, CCE, callerCtx)) + state = removePendingInitLoop(state, CCE, callerCtx); + } } if (const auto *CNE = dyn_cast<CXXNewExpr>(CE)) { @@ -815,8 +819,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, // We still allow construction into ElementRegion targets when they don't // represent array elements. if (CallOpts.IsArrayCtorOrDtor) { - if (!shouldInlineArrayConstruction( - dyn_cast<ArrayType>(CtorExpr->getType()))) + if (!shouldInlineArrayConstruction(Pred->getState(), CtorExpr, CurLC)) return CIP_DisallowedOnce; } @@ -1082,10 +1085,14 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D, return true; } -bool ExprEngine::shouldInlineArrayConstruction(const ArrayType *Type) { - if (!Type) +bool ExprEngine::shouldInlineArrayConstruction(const ProgramStateRef State, + const CXXConstructExpr *CE, + const LocationContext *LCtx) { + if (!CE) return false; + auto Type = CE->getType(); + // FIXME: Handle other arrays types. if (const auto *CAT = dyn_cast<ConstantArrayType>(Type)) { unsigned Size = getContext().getConstantArrayElementCount(CAT); @@ -1093,6 +1100,10 @@ bool ExprEngine::shouldInlineArrayConstruction(const ArrayType *Type) { return Size <= AMgr.options.maxBlockVisitOnPath; } + // Check if we're inside an ArrayInitLoopExpr, and it's sufficiently small. + if (auto Size = getPendingInitLoop(State, CE, LCtx)) + return *Size <= AMgr.options.maxBlockVisitOnPath; + return false; } @@ -1111,6 +1122,9 @@ bool ExprEngine::shouldRepeatCtorCall(ProgramStateRef State, return Size > getIndexOfElementToConstruct(State, E, LCtx); } + if (auto Size = getPendingInitLoop(State, E, LCtx)) + return Size > getIndexOfElementToConstruct(State, E, LCtx); + return false; } diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 5e946483a93d..d8ece9f39a25 100644 --- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1888,6 +1888,30 @@ SVal RegionStoreManager::getSValFromStringLiteral(const StringLiteral *SL, return svalBuilder.makeIntVal(Code, ElemT); } +static Optional<SVal> getDerivedSymbolForBinding( + RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, + const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB) { + assert(BaseRegion); + QualType BaseTy = BaseRegion->getValueType(); + QualType Ty = SubReg->getValueType(); + if (BaseTy->isScalarType() && Ty->isScalarType()) { + if (Ctx.getTypeSizeInChars(BaseTy) >= Ctx.getTypeSizeInChars(Ty)) { + if (const Optional<SVal> &ParentValue = B.getDirectBinding(BaseRegion)) { + if (SymbolRef ParentValueAsSym = ParentValue->getAsSymbol()) + return SVB.getDerivedRegionValueSymbolVal(ParentValueAsSym, SubReg); + + if (ParentValue->isUndef()) + return UndefinedVal(); + + // Other cases: give up. We are indexing into a larger object + // that has some value, but we don't know how to handle that yet. + return UnknownVal(); + } + } + } + return None; +} + SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B, const ElementRegion* R) { // Check if the region has a binding. @@ -1932,27 +1956,10 @@ SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B, if (!O.getRegion()) return UnknownVal(); - if (const TypedValueRegion *baseR = - dyn_cast_or_null<TypedValueRegion>(O.getRegion())) { - QualType baseT = baseR->getValueType(); - if (baseT->isScalarType()) { - QualType elemT = R->getElementType(); - if (elemT->isScalarType()) { - if (Ctx.getTypeSizeInChars(baseT) >= Ctx.getTypeSizeInChars(elemT)) { - if (const Optional<SVal> &V = B.getDirectBinding(superR)) { - if (SymbolRef parentSym = V->getAsSymbol()) - return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R); - - if (V->isUnknownOrUndef()) - return *V; - // Other cases: give up. We are indexing into a larger object - // that has some value, but we don't know how to handle that yet. - return UnknownVal(); - } - } - } - } - } + if (const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.getRegion())) + if (auto V = getDerivedSymbolForBinding(B, baseR, R, Ctx, svalBuilder)) + return *V; + return getBindingForFieldOrElementCommon(B, R, R->getElementType()); } @@ -1988,6 +1995,26 @@ SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B, } } + // Handle the case where we are accessing into a larger scalar object. + // For example, this handles: + // struct header { + // unsigned a : 1; + // unsigned b : 1; + // }; + // struct parse_t { + // unsigned bits0 : 1; + // unsigned bits2 : 2; // <-- header + // unsigned bits4 : 4; + // }; + // int parse(parse_t *p) { + // unsigned copy = p->bits2; + // header *bits = (header *)© + // return bits->b; <-- here + // } + if (const auto *Base = dyn_cast<TypedValueRegion>(R->getBaseRegion())) + if (auto V = getDerivedSymbolForBinding(B, Base, R, Ctx, svalBuilder)) + return *V; + return getBindingForFieldOrElementCommon(B, R, Ty); } diff --git a/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp index 19eb65b39b0a..513e6376f5ae 100644 --- a/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp +++ b/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp @@ -873,27 +873,6 @@ RVVIntrinsic::RVVIntrinsic( Name += "_m"; } - // Init RISC-V extensions - for (const auto &T : OutInTypes) { - if (T->isFloatVector(16) || T->isFloat(16)) - RISCVPredefinedMacros |= RISCVPredefinedMacro::Zvfh; - if (T->isFloatVector(32)) - RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp32; - if (T->isFloatVector(64)) - RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp64; - if (T->isVector(64)) - RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELen64; - } - for (auto Feature : RequiredFeatures) { - if (Feature == "RV64") - RISCVPredefinedMacros |= RISCVPredefinedMacro::RV64; - // Note: Full multiply instruction (mulh, mulhu, mulhsu, smul) for EEW=64 - // require V. - if (Feature == "FullMultiply" && - (RISCVPredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)) - RISCVPredefinedMacros |= RISCVPredefinedMacro::V; - } - // Init OutputType and InputTypes OutputType = OutInTypes[0]; InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end()); @@ -930,6 +909,48 @@ std::string RVVIntrinsic::getSuffixStr( return join(SuffixStrs, "_"); } +llvm::SmallVector<PrototypeDescriptor> +RVVIntrinsic::computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype, + bool IsMasked, bool HasMaskedOffOperand, + bool HasVL, unsigned NF) { + SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(), + Prototype.end()); + if (IsMasked) { + // If HasMaskedOffOperand, insert result type as first input operand. + if (HasMaskedOffOperand) { + if (NF == 1) { + NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]); + } else { + // Convert + // (void, op0 address, op1 address, ...) + // to + // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) + PrototypeDescriptor MaskoffType = NewPrototype[1]; + MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer); + for (unsigned I = 0; I < NF; ++I) + NewPrototype.insert(NewPrototype.begin() + NF + 1, MaskoffType); + } + } + if (HasMaskedOffOperand && NF > 1) { + // Convert + // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) + // to + // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1, + // ...) + NewPrototype.insert(NewPrototype.begin() + NF + 1, + PrototypeDescriptor::Mask); + } else { + // If IsMasked, insert PrototypeDescriptor:Mask as first input operand. + NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask); + } + } + + // If HasVL, append PrototypeDescriptor:VL to last operand + if (HasVL) + NewPrototype.push_back(PrototypeDescriptor::VL); + return NewPrototype; +} + SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) { SmallVector<PrototypeDescriptor> PrototypeDescriptors; const StringRef Primaries("evwqom0ztul"); @@ -951,5 +972,30 @@ SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) { return PrototypeDescriptors; } +raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) { + OS << "{"; + OS << "\"" << Record.Name << "\","; + if (Record.OverloadedName == nullptr || + StringRef(Record.OverloadedName).empty()) + OS << "nullptr,"; + else + OS << "\"" << Record.OverloadedName << "\","; + OS << Record.PrototypeIndex << ","; + OS << Record.SuffixIndex << ","; + OS << Record.OverloadedSuffixIndex << ","; + OS << (int)Record.PrototypeLength << ","; + OS << (int)Record.SuffixLength << ","; + OS << (int)Record.OverloadedSuffixSize << ","; + OS << (int)Record.RequiredExtensions << ","; + OS << (int)Record.TypeRangeMask << ","; + OS << (int)Record.Log2LMULMask << ","; + OS << (int)Record.NF << ","; + OS << (int)Record.HasMasked << ","; + OS << (int)Record.HasVL << ","; + OS << (int)Record.HasMaskedOffOperand << ","; + OS << "},\n"; + return OS; +} + } // end namespace RISCV } // end namespace clang diff --git a/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp b/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp index db4cd77d8c53..fc5f705b7fd4 100644 --- a/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/contrib/llvm-project/clang/utils/TableGen/RISCVVEmitter.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -29,6 +30,60 @@ using namespace llvm; using namespace clang::RISCV; namespace { +struct SemaRecord { + // Intrinsic name, e.g. vadd_vv + std::string Name; + + // Overloaded intrinsic name, could be empty if can be computed from Name + // e.g. vadd + std::string OverloadedName; + + // Supported type, mask of BasicType. + unsigned TypeRangeMask; + + // Supported LMUL. + unsigned Log2LMULMask; + + // Required extensions for this intrinsic. + unsigned RequiredExtensions; + + // Prototype for this intrinsic. + SmallVector<PrototypeDescriptor> Prototype; + + // Suffix of intrinsic name. + SmallVector<PrototypeDescriptor> Suffix; + + // Suffix of overloaded intrinsic name. + SmallVector<PrototypeDescriptor> OverloadedSuffix; + + // Number of field, large than 1 if it's segment load/store. + unsigned NF; + + bool HasMasked :1; + bool HasVL :1; + bool HasMaskedOffOperand :1; +}; + +// Compressed function signature table. +class SemaSignatureTable { +private: + std::vector<PrototypeDescriptor> SignatureTable; + + void insert(ArrayRef<PrototypeDescriptor> Signature); + +public: + static constexpr unsigned INVALID_INDEX = ~0U; + + // Create compressed signature table from SemaRecords. + void init(ArrayRef<SemaRecord> SemaRecords); + + // Query the Signature, return INVALID_INDEX if not found. + unsigned getIndex(ArrayRef<PrototypeDescriptor> Signature); + + /// Print signature table in RVVHeader Record to \p OS + void print(raw_ostream &OS); +}; + class RVVEmitter { private: RecordKeeper &Records; @@ -45,22 +100,22 @@ public: /// Emit all the information needed to map builtin -> LLVM IR intrinsic. void createCodeGen(raw_ostream &o); + /// Emit all the information needed by SemaRISCVVectorLookup.cpp. + /// We've large number of intrinsic function for RVV, creating a customized + /// could speed up the compilation time. + void createSema(raw_ostream &o); + private: - /// Create all intrinsics and add them to \p Out - void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out); + /// Create all intrinsics and add them to \p Out and SemaRecords. + void createRVVIntrinsics(std::vector<std::unique_ptr<RVVIntrinsic>> &Out, + std::vector<SemaRecord> *SemaRecords = nullptr); + /// Create all intrinsic records and SemaSignatureTable from SemaRecords. + void createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out, + SemaSignatureTable &SST, + ArrayRef<SemaRecord> SemaRecords); + /// Print HeaderCode in RVVHeader Record to \p Out void printHeaderCode(raw_ostream &OS); - - /// Emit Acrh predecessor definitions and body, assume the element of Defs are - /// sorted by extension. - void emitArchMacroAndBody( - std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &o, - std::function<void(raw_ostream &, const RVVIntrinsic &)>); - - // Emit the architecture preprocessor definitions. Return true when emits - // non-empty string. - bool emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros, - raw_ostream &o); }; } // namespace @@ -151,33 +206,82 @@ void emitCodeGenSwitchBody(const RVVIntrinsic *RVVI, raw_ostream &OS) { OS << " break;\n"; } -void emitIntrinsicFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) { - OS << "__attribute__((__clang_builtin_alias__("; - OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n"; - OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getName() << "("; - // Emit function arguments - const RVVTypes &InputTypes = RVVI.getInputTypes(); - if (!InputTypes.empty()) { - ListSeparator LS; - for (unsigned i = 0; i < InputTypes.size(); ++i) - OS << LS << InputTypes[i]->getTypeStr(); - } - OS << ");\n"; +//===----------------------------------------------------------------------===// +// SemaSignatureTable implementation +//===----------------------------------------------------------------------===// +void SemaSignatureTable::init(ArrayRef<SemaRecord> SemaRecords) { + // Sort signature entries by length, let longer signature insert first, to + // make it more possible to reuse table entries, that can reduce ~10% table + // size. + struct Compare { + bool operator()(const SmallVector<PrototypeDescriptor> &A, + const SmallVector<PrototypeDescriptor> &B) const { + if (A.size() != B.size()) + return A.size() > B.size(); + + size_t Len = A.size(); + for (size_t i = 0; i < Len; ++i) { + if (A[i] != B[i]) + return A[i] < B[i]; + } + + return false; + } + }; + + std::set<SmallVector<PrototypeDescriptor>, Compare> Signatures; + auto InsertToSignatureSet = + [&](const SmallVector<PrototypeDescriptor> &Signature) { + if (Signature.empty()) + return; + + Signatures.insert(Signature); + }; + + assert(!SemaRecords.empty()); + + llvm::for_each(SemaRecords, [&](const SemaRecord &SR) { + InsertToSignatureSet(SR.Prototype); + InsertToSignatureSet(SR.Suffix); + InsertToSignatureSet(SR.OverloadedSuffix); + }); + + llvm::for_each(Signatures, [this](auto &Sig) { insert(Sig); }); +} + +void SemaSignatureTable::insert(ArrayRef<PrototypeDescriptor> Signature) { + if (getIndex(Signature) != INVALID_INDEX) + return; + + // Insert Signature into SignatureTable if not found in the table. + SignatureTable.insert(SignatureTable.begin(), Signature.begin(), + Signature.end()); } -void emitOverloadedFuncDef(const RVVIntrinsic &RVVI, raw_ostream &OS) { - OS << "__attribute__((__clang_builtin_alias__("; - OS << "__builtin_rvv_" << RVVI.getBuiltinName() << ")))\n"; - OS << RVVI.getOutputType()->getTypeStr() << " " << RVVI.getOverloadedName() - << "("; - // Emit function arguments - const RVVTypes &InputTypes = RVVI.getInputTypes(); - if (!InputTypes.empty()) { - ListSeparator LS; - for (unsigned i = 0; i < InputTypes.size(); ++i) - OS << LS << InputTypes[i]->getTypeStr(); +unsigned SemaSignatureTable::getIndex(ArrayRef<PrototypeDescriptor> Signature) { + // Empty signature could be point into any index since there is length + // field when we use, so just always point it to 0. + if (Signature.empty()) + return 0; + + // Checking Signature already in table or not. + if (Signature.size() < SignatureTable.size()) { + size_t Bound = SignatureTable.size() - Signature.size() + 1; + for (size_t Index = 0; Index < Bound; ++Index) { + if (equal(Signature.begin(), Signature.end(), + SignatureTable.begin() + Index)) + return Index; + } } - OS << ");\n"; + + return INVALID_INDEX; +} + +void SemaSignatureTable::print(raw_ostream &OS) { + for (const auto &Sig : SignatureTable) + OS << "PrototypeDescriptor(" << static_cast<int>(Sig.PT) << ", " + << static_cast<int>(Sig.VTM) << ", " << static_cast<int>(Sig.TM) + << "),\n"; } //===----------------------------------------------------------------------===// @@ -212,10 +316,9 @@ void RVVEmitter::createHeader(raw_ostream &OS) { OS << "extern \"C\" {\n"; OS << "#endif\n\n"; - printHeaderCode(OS); + OS << "#pragma clang riscv intrinsic vector\n\n"; - std::vector<std::unique_ptr<RVVIntrinsic>> Defs; - createRVVIntrinsics(Defs); + printHeaderCode(OS); auto printType = [&](auto T) { OS << "typedef " << T->getClangBuiltinStr() << " " << T->getTypeStr() @@ -255,7 +358,7 @@ void RVVEmitter::createHeader(raw_ostream &OS) { } OS << "#endif\n"; - OS << "#if defined(__riscv_f)\n"; + OS << "#if (__riscv_v_elen_fp >= 32)\n"; for (int Log2LMUL : Log2LMULs) { auto T = RVVType::computeType(BasicType::Float32, Log2LMUL, PrototypeDescriptor::Vector); @@ -264,7 +367,7 @@ void RVVEmitter::createHeader(raw_ostream &OS) { } OS << "#endif\n"; - OS << "#if defined(__riscv_d)\n"; + OS << "#if (__riscv_v_elen_fp >= 64)\n"; for (int Log2LMUL : Log2LMULs) { auto T = RVVType::computeType(BasicType::Float64, Log2LMUL, PrototypeDescriptor::Vector); @@ -273,37 +376,8 @@ void RVVEmitter::createHeader(raw_ostream &OS) { } OS << "#endif\n\n"; - // The same extension include in the same arch guard marco. - llvm::stable_sort(Defs, [](const std::unique_ptr<RVVIntrinsic> &A, - const std::unique_ptr<RVVIntrinsic> &B) { - return A->getRISCVPredefinedMacros() < B->getRISCVPredefinedMacros(); - }); - - OS << "#define __rvv_ai static __inline__\n"; - - // Print intrinsic functions with macro - emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) { - OS << "__rvv_ai "; - emitIntrinsicFuncDef(Inst, OS); - }); - - OS << "#undef __rvv_ai\n\n"; - OS << "#define __riscv_v_intrinsic_overloading 1\n"; - // Print Overloaded APIs - OS << "#define __rvv_aio static __inline__ " - "__attribute__((__overloadable__))\n"; - - emitArchMacroAndBody(Defs, OS, [](raw_ostream &OS, const RVVIntrinsic &Inst) { - if (!Inst.isMasked() && !Inst.hasUnMaskedOverloaded()) - return; - OS << "__rvv_aio "; - emitOverloadedFuncDef(Inst, OS); - }); - - OS << "#undef __rvv_aio\n"; - OS << "\n#ifdef __cplusplus\n"; OS << "}\n"; OS << "#endif // __cplusplus\n"; @@ -392,7 +466,8 @@ void RVVEmitter::createCodeGen(raw_ostream &OS) { } void RVVEmitter::createRVVIntrinsics( - std::vector<std::unique_ptr<RVVIntrinsic>> &Out) { + std::vector<std::unique_ptr<RVVIntrinsic>> &Out, + std::vector<SemaRecord> *SemaRecords) { std::vector<Record *> RV = Records.getAllDerivedDefinitions("RVVBuiltin"); for (auto *R : RV) { StringRef Name = R->getValueAsString("Name"); @@ -404,12 +479,12 @@ void RVVEmitter::createRVVIntrinsics( bool HasMasked = R->getValueAsBit("HasMasked"); bool HasMaskedOffOperand = R->getValueAsBit("HasMaskedOffOperand"); bool HasVL = R->getValueAsBit("HasVL"); - Record *MaskedPolicyRecord = R->getValueAsDef("MaskedPolicy"); - PolicyScheme MaskedPolicy = - static_cast<PolicyScheme>(MaskedPolicyRecord->getValueAsInt("Value")); - Record *UnMaskedPolicyRecord = R->getValueAsDef("UnMaskedPolicy"); - PolicyScheme UnMaskedPolicy = - static_cast<PolicyScheme>(UnMaskedPolicyRecord->getValueAsInt("Value")); + Record *MPSRecord = R->getValueAsDef("MaskedPolicyScheme"); + auto MaskedPolicyScheme = + static_cast<PolicyScheme>(MPSRecord->getValueAsInt("Value")); + Record *UMPSRecord = R->getValueAsDef("UnMaskedPolicyScheme"); + auto UnMaskedPolicyScheme = + static_cast<PolicyScheme>(UMPSRecord->getValueAsInt("Value")); bool HasUnMaskedOverloaded = R->getValueAsBit("HasUnMaskedOverloaded"); std::vector<int64_t> Log2LMULList = R->getValueAsListOfInts("Log2LMUL"); bool HasBuiltinAlias = R->getValueAsBit("HasBuiltinAlias"); @@ -425,50 +500,19 @@ void RVVEmitter::createRVVIntrinsics( // Parse prototype and create a list of primitive type with transformers // (operand) in Prototype. Prototype[0] is output operand. - SmallVector<PrototypeDescriptor> Prototype = parsePrototypes(Prototypes); + SmallVector<PrototypeDescriptor> BasicPrototype = + parsePrototypes(Prototypes); SmallVector<PrototypeDescriptor> SuffixDesc = parsePrototypes(SuffixProto); SmallVector<PrototypeDescriptor> OverloadedSuffixDesc = parsePrototypes(OverloadedSuffixProto); // Compute Builtin types - SmallVector<PrototypeDescriptor> MaskedPrototype = Prototype; - if (HasMasked) { - // If HasMaskedOffOperand, insert result type as first input operand. - if (HasMaskedOffOperand) { - if (NF == 1) { - MaskedPrototype.insert(MaskedPrototype.begin() + 1, Prototype[0]); - } else { - // Convert - // (void, op0 address, op1 address, ...) - // to - // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) - PrototypeDescriptor MaskoffType = Prototype[1]; - MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer); - for (unsigned I = 0; I < NF; ++I) - MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1, - MaskoffType); - } - } - if (HasMaskedOffOperand && NF > 1) { - // Convert - // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) - // to - // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1, - // ...) - MaskedPrototype.insert(MaskedPrototype.begin() + NF + 1, - PrototypeDescriptor::Mask); - } else { - // If HasMasked, insert PrototypeDescriptor:Mask as first input operand. - MaskedPrototype.insert(MaskedPrototype.begin() + 1, - PrototypeDescriptor::Mask); - } - } - // If HasVL, append PrototypeDescriptor:VL to last operand - if (HasVL) { - Prototype.push_back(PrototypeDescriptor::VL); - MaskedPrototype.push_back(PrototypeDescriptor::VL); - } + auto Prototype = RVVIntrinsic::computeBuiltinTypes( + BasicPrototype, /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, + HasVL, NF); + auto MaskedPrototype = RVVIntrinsic::computeBuiltinTypes( + BasicPrototype, /*IsMasked=*/true, HasMaskedOffOperand, HasVL, NF); // Create Intrinsics for each type and LMUL. for (char I : TypeRange) { @@ -487,7 +531,7 @@ void RVVEmitter::createRVVIntrinsics( Out.push_back(std::make_unique<RVVIntrinsic>( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, IRName, /*IsMasked=*/false, /*HasMaskedOffOperand=*/false, HasVL, - UnMaskedPolicy, HasUnMaskedOverloaded, HasBuiltinAlias, + UnMaskedPolicyScheme, HasUnMaskedOverloaded, HasBuiltinAlias, ManualCodegen, *Types, IntrinsicTypes, RequiredFeatures, NF)); if (HasMasked) { // Create a masked intrinsic @@ -496,12 +540,57 @@ void RVVEmitter::createRVVIntrinsics( Out.push_back(std::make_unique<RVVIntrinsic>( Name, SuffixStr, OverloadedName, OverloadedSuffixStr, MaskedIRName, - /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicy, + /*IsMasked=*/true, HasMaskedOffOperand, HasVL, MaskedPolicyScheme, HasUnMaskedOverloaded, HasBuiltinAlias, MaskedManualCodegen, *MaskTypes, IntrinsicTypes, RequiredFeatures, NF)); } } // end for Log2LMULList } // end for TypeRange + + // We don't emit vsetvli and vsetvlimax for SemaRecord. + // They are written in riscv_vector.td and will emit those marco define in + // riscv_vector.h + if (Name == "vsetvli" || Name == "vsetvlimax") + continue; + + if (!SemaRecords) + continue; + + // Create SemaRecord + SemaRecord SR; + SR.Name = Name.str(); + SR.OverloadedName = OverloadedName.str(); + BasicType TypeRangeMask = BasicType::Unknown; + for (char I : TypeRange) + TypeRangeMask |= ParseBasicType(I); + + SR.TypeRangeMask = static_cast<unsigned>(TypeRangeMask); + + unsigned Log2LMULMask = 0; + for (int Log2LMUL : Log2LMULList) + Log2LMULMask |= 1 << (Log2LMUL + 3); + + SR.Log2LMULMask = Log2LMULMask; + + SR.RequiredExtensions = 0; + for (auto RequiredFeature : RequiredFeatures) { + RVVRequire RequireExt = StringSwitch<RVVRequire>(RequiredFeature) + .Case("RV64", RVV_REQ_RV64) + .Case("FullMultiply", RVV_REQ_FullMultiply) + .Default(RVV_REQ_None); + assert(RequireExt != RVV_REQ_None && "Unrecognized required feature?"); + SR.RequiredExtensions |= RequireExt; + } + + SR.NF = NF; + SR.HasMasked = HasMasked; + SR.HasVL = HasVL; + SR.HasMaskedOffOperand = HasMaskedOffOperand; + SR.Prototype = std::move(BasicPrototype); + SR.Suffix = parsePrototypes(SuffixProto); + SR.OverloadedSuffix = parsePrototypes(OverloadedSuffixProto); + + SemaRecords->push_back(SR); } } @@ -514,47 +603,59 @@ void RVVEmitter::printHeaderCode(raw_ostream &OS) { } } -void RVVEmitter::emitArchMacroAndBody( - std::vector<std::unique_ptr<RVVIntrinsic>> &Defs, raw_ostream &OS, - std::function<void(raw_ostream &, const RVVIntrinsic &)> PrintBody) { - RISCVPredefinedMacroT PrevMacros = - (*Defs.begin())->getRISCVPredefinedMacros(); - bool NeedEndif = emitMacroRestrictionStr(PrevMacros, OS); - for (auto &Def : Defs) { - RISCVPredefinedMacroT CurMacros = Def->getRISCVPredefinedMacros(); - if (CurMacros != PrevMacros) { - if (NeedEndif) - OS << "#endif\n\n"; - NeedEndif = emitMacroRestrictionStr(CurMacros, OS); - PrevMacros = CurMacros; - } - if (Def->hasBuiltinAlias()) - PrintBody(OS, *Def); +void RVVEmitter::createRVVIntrinsicRecords(std::vector<RVVIntrinsicRecord> &Out, + SemaSignatureTable &SST, + ArrayRef<SemaRecord> SemaRecords) { + SST.init(SemaRecords); + + for (const auto &SR : SemaRecords) { + Out.emplace_back(RVVIntrinsicRecord()); + RVVIntrinsicRecord &R = Out.back(); + R.Name = SR.Name.c_str(); + R.OverloadedName = SR.OverloadedName.c_str(); + R.PrototypeIndex = SST.getIndex(SR.Prototype); + R.SuffixIndex = SST.getIndex(SR.Suffix); + R.OverloadedSuffixIndex = SST.getIndex(SR.OverloadedSuffix); + R.PrototypeLength = SR.Prototype.size(); + R.SuffixLength = SR.Suffix.size(); + R.OverloadedSuffixSize = SR.OverloadedSuffix.size(); + R.RequiredExtensions = SR.RequiredExtensions; + R.TypeRangeMask = SR.TypeRangeMask; + R.Log2LMULMask = SR.Log2LMULMask; + R.NF = SR.NF; + R.HasMasked = SR.HasMasked; + R.HasVL = SR.HasVL; + R.HasMaskedOffOperand = SR.HasMaskedOffOperand; + + assert(R.PrototypeIndex != + static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX)); + assert(R.SuffixIndex != + static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX)); + assert(R.OverloadedSuffixIndex != + static_cast<uint16_t>(SemaSignatureTable::INVALID_INDEX)); } - if (NeedEndif) - OS << "#endif\n\n"; } -bool RVVEmitter::emitMacroRestrictionStr(RISCVPredefinedMacroT PredefinedMacros, - raw_ostream &OS) { - if (PredefinedMacros == RISCVPredefinedMacro::Basic) - return false; - OS << "#if "; - ListSeparator LS(" && "); - if (PredefinedMacros & RISCVPredefinedMacro::V) - OS << LS << "defined(__riscv_v)"; - if (PredefinedMacros & RISCVPredefinedMacro::Zvfh) - OS << LS << "defined(__riscv_zvfh)"; - if (PredefinedMacros & RISCVPredefinedMacro::RV64) - OS << LS << "(__riscv_xlen == 64)"; - if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64) - OS << LS << "(__riscv_v_elen >= 64)"; - if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp32) - OS << LS << "(__riscv_v_elen_fp >= 32)"; - if (PredefinedMacros & RISCVPredefinedMacro::VectorMaxELenFp64) - OS << LS << "(__riscv_v_elen_fp >= 64)"; - OS << "\n"; - return true; +void RVVEmitter::createSema(raw_ostream &OS) { + std::vector<std::unique_ptr<RVVIntrinsic>> Defs; + std::vector<RVVIntrinsicRecord> RVVIntrinsicRecords; + SemaSignatureTable SST; + std::vector<SemaRecord> SemaRecords; + + createRVVIntrinsics(Defs, &SemaRecords); + + createRVVIntrinsicRecords(RVVIntrinsicRecords, SST, SemaRecords); + + // Emit signature table for SemaRISCVVectorLookup.cpp. + OS << "#ifdef DECL_SIGNATURE_TABLE\n"; + SST.print(OS); + OS << "#endif\n"; + + // Emit RVVIntrinsicRecords for SemaRISCVVectorLookup.cpp. + OS << "#ifdef DECL_INTRINSIC_RECORDS\n"; + for (const RVVIntrinsicRecord &Record : RVVIntrinsicRecords) + OS << Record; + OS << "#endif\n"; } namespace clang { @@ -570,4 +671,8 @@ void EmitRVVBuiltinCG(RecordKeeper &Records, raw_ostream &OS) { RVVEmitter(Records).createCodeGen(OS); } +void EmitRVVBuiltinSema(RecordKeeper &Records, raw_ostream &OS) { + RVVEmitter(Records).createSema(OS); +} + } // End namespace clang diff --git a/contrib/llvm-project/clang/utils/TableGen/TableGen.cpp b/contrib/llvm-project/clang/utils/TableGen/TableGen.cpp index bb9366e2b7fc..d18a31226e80 100644 --- a/contrib/llvm-project/clang/utils/TableGen/TableGen.cpp +++ b/contrib/llvm-project/clang/utils/TableGen/TableGen.cpp @@ -88,6 +88,7 @@ enum ActionType { GenRISCVVectorHeader, GenRISCVVectorBuiltins, GenRISCVVectorBuiltinCG, + GenRISCVVectorBuiltinSema, GenAttrDocs, GenDiagDocs, GenOptDocs, @@ -243,6 +244,8 @@ cl::opt<ActionType> Action( "Generate riscv_vector_builtins.inc for clang"), clEnumValN(GenRISCVVectorBuiltinCG, "gen-riscv-vector-builtin-codegen", "Generate riscv_vector_builtin_cg.inc for clang"), + clEnumValN(GenRISCVVectorBuiltinSema, "gen-riscv-vector-builtin-sema", + "Generate riscv_vector_builtin_sema.inc for clang"), clEnumValN(GenAttrDocs, "gen-attr-docs", "Generate attribute documentation"), clEnumValN(GenDiagDocs, "gen-diag-docs", @@ -458,6 +461,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenRISCVVectorBuiltinCG: EmitRVVBuiltinCG(Records, OS); break; + case GenRISCVVectorBuiltinSema: + EmitRVVBuiltinSema(Records, OS); + break; case GenAttrDocs: EmitClangAttrDocs(Records, OS); break; diff --git a/contrib/llvm-project/clang/utils/TableGen/TableGenBackends.h b/contrib/llvm-project/clang/utils/TableGen/TableGenBackends.h index fd8b9fcda20f..2ba857f66f50 100644 --- a/contrib/llvm-project/clang/utils/TableGen/TableGenBackends.h +++ b/contrib/llvm-project/clang/utils/TableGen/TableGenBackends.h @@ -110,6 +110,7 @@ void EmitMveBuiltinAliases(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitRVVHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitRVVBuiltins(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitRVVBuiltinCG(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitRVVBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitCdeHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitCdeBuiltinDef(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); |