diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h index 72f96d0945625..075b5f0ce450a 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h @@ -25,6 +25,9 @@ namespace readability { /// This check is similar to `-Wold-style-cast`, but it suggests automated fixes /// in some cases. The reported locations should not be different from the /// ones generated by `-Wold-style-cast`. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-casting.html class AvoidCStyleCastsCheck : public ClangTidyCheck { public: AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h index 6a690f60da1c2..a9989ee51bcf6 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h +++ b/clang-tools-extra/clang-tidy/google/AvoidUnderscoreInGoogletestNameCheck.h @@ -18,6 +18,9 @@ namespace readability { // Check for underscores in the names of googletest tests, per // https://github.com/google/googletest/blob/master/googletest/docs/faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-avoid-underscore-in-googletest-name.html class AvoidUnderscoreInGoogletestNameCheck : public ClangTidyCheck { public: using ClangTidyCheck::ClangTidyCheck; diff --git a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h index 574965dc556a6..089d463ff9852 100644 --- a/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h +++ b/clang-tools-extra/clang-tidy/google/DefaultArgumentsCheck.h @@ -18,6 +18,9 @@ namespace google { /// Checks that default parameters are not given for virtual methods. /// /// See https://google.github.io/styleguide/cppguide.html#Default_Arguments +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-default-arguments.html class DefaultArgumentsCheck : public ClangTidyCheck { public: DefaultArgumentsCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h index 721ad4efc9797..573b0e18f90db 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.h @@ -18,6 +18,9 @@ namespace google { /// Checks that all single-argument constructors are explicit. /// /// See https://google.github.io/styleguide/cppguide.html#Explicit_Constructors +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-explicit-constructor.html class ExplicitConstructorCheck : public ClangTidyCheck { public: ExplicitConstructorCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h b/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h index dae66c8afa8b9..56ca5b20966e1 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h +++ b/clang-tools-extra/clang-tidy/google/ExplicitMakePairCheck.h @@ -22,6 +22,9 @@ namespace build { /// specified explicitly, and such use isn't intended in any case. /// /// Corresponding cpplint.py check name: 'build/explicit_make_pair'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-build-explicit-make-pair.html class ExplicitMakePairCheck : public ClangTidyCheck { public: ExplicitMakePairCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h index aa569dedcdb4b..801d362aa5094 100644 --- a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h +++ b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.h @@ -27,6 +27,9 @@ namespace readability { /// /// For extension-less header files, using an empty string or leaving an /// empty string between ";" if there are other filename extensions. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-global-names-in-headers.html class GlobalNamesInHeadersCheck : public ClangTidyCheck { public: GlobalNamesInHeadersCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h index 0b528dab2476d..5b2d2f501c91a 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h @@ -25,6 +25,9 @@ namespace runtime { /// with `u?intXX(_t)?`. /// /// Corresponding cpplint.py check: 'runtime/int'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-runtime-int.html class IntegerTypesCheck : public ClangTidyCheck { public: IntegerTypesCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h b/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h index 33cf4d62a45a6..7f513387ed616 100644 --- a/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h +++ b/clang-tools-extra/clang-tidy/google/OverloadedUnaryAndCheck.h @@ -21,6 +21,9 @@ namespace runtime { /// https://google.github.io/styleguide/cppguide.html#Operator_Overloading /// /// Corresponding cpplint.py check name: 'runtime/operator'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-runtime-operator.html class OverloadedUnaryAndCheck : public ClangTidyCheck { public: OverloadedUnaryAndCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h index 8c32dddc28373..ee14997f1506d 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h @@ -19,6 +19,9 @@ namespace readability { /// Finds TODO comments without a username or bug number. /// /// Corresponding cpplint.py check: 'readability/todo' +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-readability-todo.html class TodoCommentCheck : public ClangTidyCheck { public: TodoCommentCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h index 52af823e6a0e1..22110215a5efe 100644 --- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h +++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.h @@ -30,6 +30,9 @@ namespace build { /// https://google.github.io/styleguide/cppguide.html#Namespaces /// /// Corresponding cpplint.py check name: 'build/namespaces'. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-build-namespaces.html class UnnamedNamespaceInHeaderCheck : public ClangTidyCheck { public: UnnamedNamespaceInHeaderCheck(StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h index 97a1afbf160fe..c1b86c953fc59 100644 --- a/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h +++ b/clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h @@ -31,6 +31,9 @@ namespace build { /// \endcode /// /// Corresponding cpplint.py check name: `build/namespaces`. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/google-build-using-namespace.html class UsingNamespaceDirectiveCheck : public ClangTidyCheck { public: UsingNamespaceDirectiveCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 03b4450d8ca8c..24847d80657c1 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -63,8 +63,10 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { declStmt( has(varDecl(hasLocalStorage(), hasType(qualType( - hasCanonicalType( - matchers::isExpensiveToCopy()), + hasCanonicalType(allOf( + matchers::isExpensiveToCopy(), + unless(hasDeclaration(namedDecl( + hasName("::std::function")))))), unless(hasDeclaration(namedDecl( matchers::matchesAnyListedName( AllowedTypes)))))), diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp index 7a70bc18a28c8..9055529c7a3fd 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp @@ -405,3 +405,58 @@ void negativeInitialzedFromFreeFunctionWithNonDefaultArg() { ExpensiveToCopyType Orig; const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg(&Orig); } + +namespace std { +inline namespace __1 { + +template +class function; +template +class function { +public: + function(); + function(const function &other); + R operator()(Args &&...args) const; +}; + +} // namespace __1 +} // namespace std + +void negativeStdFunction() { + std::function Orig; + std::function Copy = Orig; + int i = Orig(); +} + +using Functor = std::function; + +void negativeAliasedStdFunction() { + Functor Orig; + Functor Copy = Orig; + int i = Orig(); +} + +typedef std::function TypedefFunc; + +void negativeTypedefedStdFunction() { + TypedefFunc Orig; + TypedefFunc Copy = Orig; + int i = Orig(); +} + +namespace fake { +namespace std { +template +struct function { + // Custom copy constructor makes it expensive to copy; + function(const function &); +}; +} // namespace std + +void positiveFakeStdFunction(std::function F) { + auto Copy = F; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'Copy' of the variable 'F' is never modified; + // CHECK-FIXES: const auto& Copy = F; +} + +} // namespace fake diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 7592d84ea9ed7..9e40cf1b2a976 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -449,7 +449,6 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) PATTERN "*.def" PATTERN "*.h" PATTERN "config.h" EXCLUDE - PATTERN ".svn" EXCLUDE ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/clang diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 86bc9f637ab7e..6864f6058a3ff 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -3335,6 +3335,8 @@ X86 .. option:: -mtsxldtrk, -mno-tsxldtrk +.. option:: -muintr, -mno-uintr + .. option:: -mvaes, -mno-vaes .. option:: -mvpclmulqdq, -mno-vpclmulqdq diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 540cf91326056..56337177e060e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -200,6 +200,10 @@ X86 Support in Clang implies -mtune=. -mtune=generic is the default with no -march or -mtune specified. +- Support for ``HRESET`` instructions has been added. + +- Support for ``UINTR`` instructions has been added. + Internal API Changes -------------------- diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index 0ee48f35a20a1..6cda588ffe748 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -235,8 +235,10 @@ class APValue { struct UninitArray {}; struct UninitStruct {}; - friend class ASTReader; + friend class ASTRecordReader; friend class ASTWriter; + friend class ASTImporter; + friend class ASTNodeImporter; private: ValueKind Kind; @@ -569,11 +571,9 @@ class APValue { *(APFixedPoint *)(char *)Data.buffer = std::move(FX); } void setVector(const APValue *E, unsigned N) { - assert(isVector() && "Invalid accessor"); - ((Vec*)(char*)Data.buffer)->Elts = new APValue[N]; - ((Vec*)(char*)Data.buffer)->NumElts = N; + MutableArrayRef InternalElts = setVectorUninit(N); for (unsigned i = 0; i != N; ++i) - ((Vec*)(char*)Data.buffer)->Elts[i] = E[i]; + InternalElts[i] = E[i]; } void setComplexInt(APSInt R, APSInt I) { assert(R.getBitWidth() == I.getBitWidth() && @@ -594,11 +594,7 @@ class APValue { void setLValue(LValueBase B, const CharUnits &O, ArrayRef Path, bool OnePastTheEnd, bool IsNullPtr); - void setUnion(const FieldDecl *Field, const APValue &Value) { - assert(isUnion() && "Invalid accessor"); - ((UnionData*)(char*)Data.buffer)->Field = Field; - *((UnionData*)(char*)Data.buffer)->Value = Value; - } + void setUnion(const FieldDecl *Field, const APValue &Value); void setAddrLabelDiff(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr) { ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr; @@ -656,6 +652,24 @@ class APValue { new ((void*)(char*)Data.buffer) AddrLabelDiffData(); Kind = AddrLabelDiff; } + +private: + /// The following functions are used as part of initialization, during + /// deserialization and importing. Reserve the space so that it can be + /// filled in by those steps. + MutableArrayRef setVectorUninit(unsigned N) { + assert(isVector() && "Invalid accessor"); + Vec *V = ((Vec *)(char *)Data.buffer); + V->Elts = new APValue[N]; + V->NumElts = N; + return {V->Elts, V->NumElts}; + } + MutableArrayRef + setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + MutableArrayRef + setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size); }; } // end namespace clang. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 97facd5d3b68d..75daa122deebc 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -289,8 +289,8 @@ class ASTContext : public RefCountedBase { /// Mapping from GUIDs to the corresponding MSGuidDecl. mutable llvm::FoldingSet MSGuidDecls; - /// Used to cleanups APValues stored in the AST. - mutable llvm::SmallVector APValueCleanups; + /// Mapping from APValues to the corresponding TemplateParamObjects. + mutable llvm::FoldingSet TemplateParamObjectDecls; /// A cache mapping a string value to a StringLiteral object with the same /// value. @@ -2876,6 +2876,11 @@ class ASTContext : public RefCountedBase { /// GUID value. MSGuidDecl *getMSGuidDecl(MSGuidDeclParts Parts) const; + /// Return the template parameter object of the given type with the given + /// value. + TemplateParamObjectDecl *getTemplateParamObjectDecl(QualType T, + const APValue &V) const; + /// Parses the target attributes passed in, and returns only the ones that are /// valid feature names. ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 205d7ec67754f..a6d822ba2ea6d 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H +#include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExprCXX.h" @@ -503,6 +504,13 @@ class TypeSourceInfo; /// "to" context, or the import error. llvm::Expected Import(const CXXBaseSpecifier *FromSpec); + /// Import the given APValue from the "from" context into + /// the "to" context. + /// + /// \return the equivalent APValue in the "to" context or the import + /// error. + llvm::Expected Import(const APValue &FromValue); + /// Import the definition of the given declaration, including all of /// the declarations it contains. LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From); diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 5f35257390912..641647659c17e 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3226,7 +3226,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl { static bool classofKind(Kind K) { return K == VarTemplate; } }; -// \brief Declaration of a C++2a concept. +/// Declaration of a C++2a concept. class ConceptDecl : public TemplateDecl, public Mergeable { protected: Expr *ConstraintExpr; @@ -3255,6 +3255,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable { return isa(getTemplateParameters()->getParam(0)); } + ConceptDecl *getCanonicalDecl() override { return getFirstDecl(); } + const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Concept; } @@ -3264,6 +3267,74 @@ class ConceptDecl : public TemplateDecl, public Mergeable { friend class ASTDeclWriter; }; +/// A template parameter object. +/// +/// Template parameter objects represent values of class type used as template +/// arguments. There is one template parameter object for each such distinct +/// value used as a template argument across the program. +/// +/// \code +/// struct A { int x, y; }; +/// template struct S; +/// S s1; +/// S s2; // same type, argument is same TemplateParamObjectDecl. +/// \endcode +class TemplateParamObjectDecl : public ValueDecl, + public Mergeable, + public llvm::FoldingSetNode { +private: + /// The value of this template parameter object. + APValue Value; + + TemplateParamObjectDecl(DeclContext *DC, QualType T, const APValue &V) + : ValueDecl(TemplateParamObject, DC, SourceLocation(), DeclarationName(), + T), + Value(V) {} + + static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T, + const APValue &V); + static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + /// Only ASTContext::getTemplateParamObjectDecl and deserialization + /// create these. + friend class ASTContext; + friend class ASTReader; + friend class ASTDeclReader; + +public: + /// Print this template parameter object in a human-readable format. + void printName(llvm::raw_ostream &OS) const override; + + /// Print this object as an equivalent expression. + void printAsExpr(llvm::raw_ostream &OS) const; + + /// Print this object as an initializer suitable for a variable of the + /// object's type. + void printAsInit(llvm::raw_ostream &OS) const; + + const APValue &getValue() const { return Value; } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType T, + const APValue &V) { + ID.AddPointer(T.getCanonicalType().getAsOpaquePtr()); + V.Profile(ID); + } + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getType(), getValue()); + } + + TemplateParamObjectDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const TemplateParamObjectDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == TemplateParamObject; } +}; + inline NamedDecl *getAsNamedDecl(TemplateParameter P) { if (auto *PD = P.dyn_cast()) return PD; diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 926021e9c6ed6..61a23ddaa368b 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4233,8 +4233,10 @@ class SubstNonTypeTemplateParmExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - /// The replaced parameter. - NonTypeTemplateParmDecl *Param; + /// The replaced parameter and a flag indicating if it was a reference + /// parameter. For class NTTPs, we can't determine that based on the value + /// category alone. + llvm::PointerIntPair ParamAndRef; /// The replacement expression. Stmt *Replacement; @@ -4245,10 +4247,10 @@ class SubstNonTypeTemplateParmExpr : public Expr { public: SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, SourceLocation Loc, - NonTypeTemplateParmDecl *Param, + NonTypeTemplateParmDecl *Param, bool RefParam, Expr *Replacement) : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), - Param(Param), Replacement(Replacement) { + ParamAndRef(Param, RefParam), Replacement(Replacement) { SubstNonTypeTemplateParmExprBits.NameLoc = Loc; setDependence(computeDependence(this)); } @@ -4261,7 +4263,14 @@ class SubstNonTypeTemplateParmExpr : public Expr { Expr *getReplacement() const { return cast(Replacement); } - NonTypeTemplateParmDecl *getParameter() const { return Param; } + NonTypeTemplateParmDecl *getParameter() const { + return ParamAndRef.getPointer(); + } + + bool isReferenceParameter() const { return ParamAndRef.getInt(); } + + /// Determine the substituted type of the template parameter. + QualType getParameterType(const ASTContext &Ctx) const; static bool classof(const Stmt *s) { return s->getStmtClass() == SubstNonTypeTemplateParmExprClass; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 6f07b92f25323..5e83cded06520 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1970,6 +1970,8 @@ DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); }) DEF_TRAVERSE_DECL(MSGuidDecl, {}) +DEF_TRAVERSE_DECL(TemplateParamObjectDecl, {}) + DEF_TRAVERSE_DECL(FieldDecl, { TRY_TO(TraverseDeclaratorHelper(D)); if (D->isBitField()) diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def index f66ae78f7e81f..3e186af82ff71 100644 --- a/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -94,6 +94,12 @@ TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dUOiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fUOiIi", "ncV:128:", "avx512f") TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri") +// UINTR +TARGET_BUILTIN(__builtin_ia32_clui, "v", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_stui, "v", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_testui, "Uc", "n", "uintr") +TARGET_BUILTIN(__builtin_ia32_senduipi, "vUWi", "n", "uintr") + // AMX TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile") TARGET_BUILTIN(__builtin_ia32_tile_storeconfig, "vvC*", "n", "amx-tile") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 641b99edaed11..0ab9054f0bb5d 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -356,6 +356,9 @@ ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) /// Bit size of immediate TLS offsets (0 == use the default). VALUE_CODEGENOPT(TLSSize, 8, 0) +/// The default stack protector guard offset to use. +VALUE_CODEGENOPT(StackProtectorGuardOffset, 32, (unsigned)-1) + /// Number of path components to strip when emitting checks. (0 == full /// filename) VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index ca391bf8f1861..f658c9b8a7819 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -327,6 +327,15 @@ class CodeGenOptions : public CodeGenOptionsBase { /// by sanitizer coverage pass. std::vector SanitizeCoverageAllowlistFiles; + /// The guard style used for stack protector to get a initial value, this + /// value usually be gotten from TLS or get from __stack_chk_guard, or some + /// other styles we may implement in the future. + std::string StackProtectorGuard; + + /// The TLS base register when StackProtectorGuard is "tls". + /// On x86 this can be "fs" or "gs". + std::string StackProtectorGuardReg; + /// Path to blocklist file specifying which objects /// (files, functions) listed for instrumentation by sanitizer /// coverage pass should actually not be instrumented. diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 866988ee3f015..4771a3549426b 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -41,6 +41,7 @@ def Named : DeclNode; def OMPDeclareReduction : DeclNode, DeclContext; def OMPDeclareMapper : DeclNode, DeclContext; def MSGuid : DeclNode; + def TemplateParamObject : DeclNode; def Declarator : DeclNode; def Field : DeclNode; def ObjCIvar : DeclNode; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 5d49f41dd15ff..fd80504ca8794 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -223,6 +223,7 @@ def err_drv_dllexport_inlines_and_fallback : Error< def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; +def err_drv_invalid_value_with_suggestion : Error<"invalid value '%1' in '%0','%2'">; def err_drv_invalid_remap_file : Error< "invalid option '%0' not of the form ;">; def err_drv_invalid_gcc_output_type : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2de36ff88607d..190bb3cba4ef7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2025,8 +2025,8 @@ def err_destructor_template : Error< // C++ initialization def err_init_conversion_failed : Error< - "cannot initialize %select{a variable|a parameter|return object|" - "statement expression result|an " + "cannot initialize %select{a variable|a parameter|template parameter|" + "return object|statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " @@ -2168,7 +2168,7 @@ def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup; def select_initialized_entity_kind : TextSubstitution< - "%select{copying variable|copying parameter|" + "%select{copying variable|copying parameter|initializing template parameter|" "returning object|initializing statement expression result|" "throwing object|copying member subobject|copying array element|" "allocating object|copying temporary|initializing base subobject|" @@ -4533,6 +4533,10 @@ def note_not_structural_rvalue_ref_field : Note< def note_not_structural_subobject : Note< "%0 is not a structural type because it has a " "%select{non-static data member|base class}1 of non-structural type %2">; +def warn_cxx17_compat_template_nontype_parm_type : Warning< + "non-type template parameter of type %0 is incompatible with " + "C++ standards before C++20">, + DefaultIgnore, InGroup; def warn_cxx14_compat_template_nontype_parm_auto_type : Warning< "non-type template parameters declared with %0 are incompatible with C++ " "standards before C++17">, diff --git a/clang/include/clang/Basic/OpenCLExtensions.def b/clang/include/clang/Basic/OpenCLExtensions.def index 1ae36b32fb0a9..d67cb3ff019b4 100644 --- a/clang/include/clang/Basic/OpenCLExtensions.def +++ b/clang/include/clang/Basic/OpenCLExtensions.def @@ -23,6 +23,16 @@ // core - minimum OpenCL version when the extension becomes optional core // feature or core feature. ~0U indicates not a core feature or an // optional core feature. +// +// As per The OpenCL Extension Specification, Section 1.2, in this file, an +// extension is defined if and only it either: +// * affects the OpenCL language semantics or its syntax, +// * adds built-in functions to the language. +// +// For such an extension, a preprocessor #define that matches the extension +// name must be created and a #pragma is required if and only if the +// compilation flow is impacted, e.g. due to a difference of syntax or +// semantics in the language compared to the core standard. #ifndef OPENCLEXT_INTERNAL #ifndef OPENCLEXT @@ -34,8 +44,6 @@ // OpenCL 1.0. OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200) -// fprounding mode is special since it is not mentioned beyond 1.0 -OPENCLEXT_INTERNAL(cl_khr_select_fprounding_mode, 100, 110) OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110) OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U) OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120) @@ -45,35 +53,19 @@ OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110) OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110) OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U) OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_sharing, 100, ~0U) -OPENCLEXT_INTERNAL(cl_khr_icd, 100, ~0U) - -// OpenCL 1.1. -OPENCLEXT_INTERNAL(cl_khr_gl_event, 110, ~0U) -OPENCLEXT_INTERNAL(cl_khr_d3d10_sharing, 110, ~0U) // EMBEDDED_PROFILE OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) // OpenCL 1.2. -OPENCLEXT_INTERNAL(cl_khr_context_abort, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_d3d11_sharing, 120, ~0U) OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_dx9_media_sharing, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_image2d_from_buffer, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_initialize_memory, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_gl_depth_images, 120, ~0U) OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U) -OPENCLEXT_INTERNAL(cl_khr_spir, 120, ~0U) // OpenCL 2.0. -OPENCLEXT_INTERNAL(cl_khr_egl_event, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_egl_image, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U) -OPENCLEXT_INTERNAL(cl_khr_terminate_context, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_extended_types, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_non_uniform_vote, 200, ~0U) OPENCLEXT_INTERNAL(cl_khr_subgroup_ballot, 200, ~0U) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 7253b5ea9abed..26dc6eacb2041 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -581,8 +581,9 @@ class TargetInfo : public virtual TransferrableTargetInfo, /// Determine whether constrained floating point is supported on this target. virtual bool hasStrictFP() const { return HasStrictFP; } - /// Return the alignment that is suitable for storing any - /// object with a fundamental alignment requirement. + /// Return the alignment that is the largest alignment ever used for any + /// scalar/SIMD data type on the target machine you are compiling for + /// (including types with an extended alignment requirement). unsigned getSuitableAlign() const { return SuitableAlign; } /// Return the default alignment for __attribute__((aligned)) on diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 25daae2a0a25d..94f76dd729b0b 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -406,7 +406,7 @@ def vabdq: Intrinsic { + bit wantXVariant = 1> { defm "" : IntrinsicMX< Vector, (args Vector:$a, Vector:$b, Predicate:$pred), !con((IRInt $a, $b), @@ -415,7 +415,7 @@ multiclass VectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMXNameOverride< Vector, (args Vector:$a, unpromoted:$b, Predicate:$pred), !con((IRInt $a, (splat $b)), @@ -451,7 +451,7 @@ let params = T.Usual in { } multiclass DblVectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMX< DblVector, (args Vector:$a, Vector:$b, DblPredicate:$pred), !con((IRInt $a, $b), @@ -460,7 +460,7 @@ multiclass DblVectorVectorArithmetic { + bit wantXVariant = 1> { defm "" : IntrinsicMXNameOverride< DblVector, (args Vector:$a, unpromoted:$b, DblPredicate:$pred), !con((IRInt $a, (splat $b)), diff --git a/clang/include/clang/Basic/arm_mve_defs.td b/clang/include/clang/Basic/arm_mve_defs.td index 4038a18027f8c..1a090c08cc853 100644 --- a/clang/include/clang/Basic/arm_mve_defs.td +++ b/clang/include/clang/Basic/arm_mve_defs.td @@ -519,7 +519,7 @@ class NameOverride { // polymorph differently (typically because the type of the inactive // parameter can be used as a disambiguator if it's present). multiclass IntrinsicMX { @@ -532,7 +532,7 @@ multiclass IntrinsicMX) in { + if wantXVariant then { // The _x variant leaves off that parameter, and simply uses an // undef value of the same type. @@ -546,7 +546,7 @@ multiclass IntrinsicMX { @@ -556,7 +556,7 @@ multiclass IntrinsicMXNameOverride) in { + if wantXVariant then { def "_x" # nameSuffix: Intrinsic, NameOverride { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index ac00407352efe..fc7055ef08a0a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2670,6 +2670,12 @@ def mrecip : Flag<["-"], "mrecip">, Group; def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group, Flags<[CC1Option]>; def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group, Flags<[CC1Option]>, HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">; +def mstack_protector_guard_EQ : Joined<["-"], "mstack-protector-guard=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given guard (global, tls) for addressing the stack-protector guard">; +def mstack_protector_guard_offset_EQ : Joined<["-"], "mstack-protector-guard-offset=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given offset for addressing the stack-protector guard">; +def mstack_protector_guard_reg_EQ : Joined<["-"], "mstack-protector-guard-reg=">, Group, Flags<[CC1Option]>, + HelpText<"Use the given reg for addressing the stack-protector guard">; def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group, Flags<[CC1Option]>, HelpText<"Use copy relocations support for PIE builds">; @@ -3381,6 +3387,8 @@ def mtbm : Flag<["-"], "mtbm">, Group; def mno_tbm : Flag<["-"], "mno-tbm">, Group; def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group; def mno_tsxldtrk : Flag<["-"], "mno-tsxldtrk">, Group; +def muintr : Flag<["-"], "muintr">, Group; +def mno_uintr : Flag<["-"], "mno-uintr">, Group; def mvaes : Flag<["-"], "mvaes">, Group; def mno_vaes : Flag<["-"], "mno-vaes">, Group; def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group; diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index ca9e0a198cb91..6976e7c95c8b2 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -55,6 +55,9 @@ class alignas(8) InitializedEntity { /// The entity being initialized is a function parameter. EK_Parameter, + /// The entity being initialized is a non-type template parameter. + EK_TemplateParameter, + /// The entity being initialized is the result of a function call. EK_Result, @@ -175,7 +178,8 @@ class alignas(8) InitializedEntity { }; union { - /// When Kind == EK_Variable, EK_Member or EK_Binding, the variable. + /// When Kind == EK_Variable, EK_Member, EK_Binding, or + /// EK_TemplateParameter, the variable, binding, or template parameter. VD Variable; /// When Kind == EK_RelatedResult, the ObjectiveC method where @@ -281,6 +285,17 @@ class alignas(8) InitializedEntity { return Entity; } + /// Create the initialization entity for a template parameter. + static InitializedEntity + InitializeTemplateParameter(QualType T, NonTypeTemplateParmDecl *Param) { + InitializedEntity Entity; + Entity.Kind = EK_TemplateParameter; + Entity.Type = T; + Entity.Parent = nullptr; + Entity.Variable = {Param, false, false}; + return Entity; + } + /// Create the initialization entity for the result of a function. static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type, bool NRVO) { @@ -441,6 +456,10 @@ class alignas(8) InitializedEntity { getKind() == EK_Parameter_CF_Audited); } + bool isParamOrTemplateParamKind() const { + return isParameterKind() || getKind() == EK_TemplateParameter; + } + /// Determine whether this initialization consumes the /// parameter. bool isParameterConsumed() const { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4c01e94241554..c50749c0877ed 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3523,7 +3523,8 @@ class Sema final { ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, - APValue &Value, CCEKind CCE); + APValue &Value, CCEKind CCE, + NamedDecl *Dest = nullptr); /// Abstract base class used to perform a contextual implicit /// conversion from an expression to any type passing a filter. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 726c383ade807..52ddd57492025 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1286,6 +1286,9 @@ class TypeIdx { /// A MSGuidDecl record. DECL_MS_GUID, + /// A TemplateParamObjectDecl record. + DECL_TEMPLATE_PARAM_OBJECT, + /// A VarDecl record. DECL_VAR, diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 8d402ee8e3dca..53aa09fa9b364 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -414,7 +414,18 @@ void APValue::swap(APValue &RHS) { std::swap(Data, RHS.Data); } +/// Profile the value of an APInt, excluding its bit-width. +static void profileIntValue(llvm::FoldingSetNodeID &ID, const llvm::APInt &V) { + for (unsigned I = 0, N = V.getBitWidth(); I < N; I += 32) + ID.AddInteger((uint32_t)V.extractBitsAsZExtValue(std::min(32u, N - I), I)); +} + void APValue::Profile(llvm::FoldingSetNodeID &ID) const { + // Note that our profiling assumes that only APValues of the same type are + // ever compared. As a result, we don't consider collisions that could only + // happen if the types are different. (For example, structs with different + // numbers of members could profile the same.) + ID.AddInteger(Kind); switch (Kind) { @@ -428,25 +439,22 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const { return; case Struct: - ID.AddInteger(getStructNumBases()); for (unsigned I = 0, N = getStructNumBases(); I != N; ++I) getStructBase(I).Profile(ID); - ID.AddInteger(getStructNumFields()); for (unsigned I = 0, N = getStructNumFields(); I != N; ++I) getStructField(I).Profile(ID); return; case Union: if (!getUnionField()) { - ID.AddPointer(nullptr); + ID.AddInteger(0); return; } - ID.AddPointer(getUnionField()->getCanonicalDecl()); + ID.AddInteger(getUnionField()->getFieldIndex() + 1); getUnionValue().Profile(ID); return; case Array: { - ID.AddInteger(getArraySize()); if (getArraySize() == 0) return; @@ -502,46 +510,46 @@ void APValue::Profile(llvm::FoldingSetNodeID &ID) const { } case Vector: - ID.AddInteger(getVectorLength()); for (unsigned I = 0, N = getVectorLength(); I != N; ++I) getVectorElt(I).Profile(ID); return; case Int: - // We don't need to include the sign bit; it's implied by the type. - getInt().APInt::Profile(ID); + profileIntValue(ID, getInt()); return; case Float: - getFloat().Profile(ID); + profileIntValue(ID, getFloat().bitcastToAPInt()); return; case FixedPoint: - // We don't need to include the fixed-point semantics; they're - // implied by the type. - getFixedPoint().getValue().APInt::Profile(ID); + profileIntValue(ID, getFixedPoint().getValue()); return; case ComplexFloat: - getComplexFloatReal().Profile(ID); - getComplexFloatImag().Profile(ID); + profileIntValue(ID, getComplexFloatReal().bitcastToAPInt()); + profileIntValue(ID, getComplexFloatImag().bitcastToAPInt()); return; case ComplexInt: - getComplexIntReal().APInt::Profile(ID); - getComplexIntImag().APInt::Profile(ID); + profileIntValue(ID, getComplexIntReal()); + profileIntValue(ID, getComplexIntImag()); return; case LValue: getLValueBase().Profile(ID); ID.AddInteger(getLValueOffset().getQuantity()); - ID.AddInteger(isNullPointer()); - ID.AddInteger(isLValueOnePastTheEnd()); - // For uniqueness, we only need to profile the entries corresponding - // to union members, but we don't have the type here so we don't know - // how to interpret the entries. - for (LValuePathEntry E : getLValuePath()) - E.Profile(ID); + ID.AddInteger((isNullPointer() ? 1 : 0) | + (isLValueOnePastTheEnd() ? 2 : 0) | + (hasLValuePath() ? 4 : 0)); + if (hasLValuePath()) { + ID.AddInteger(getLValuePath().size()); + // For uniqueness, we only need to profile the entries corresponding + // to union members, but we don't have the type here so we don't know + // how to interpret the entries. + for (LValuePathEntry E : getLValuePath()) + E.Profile(ID); + } return; case MemberPointer: @@ -882,17 +890,33 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, LVal.IsNullPtr = IsNullPtr; } -void APValue::setLValue(LValueBase B, const CharUnits &O, - ArrayRef Path, bool IsOnePastTheEnd, - bool IsNullPtr) { +MutableArrayRef +APValue::setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size, + bool IsOnePastTheEnd, bool IsNullPtr) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data.buffer); + LV &LVal = *((LV *)(char *)Data.buffer); LVal.Base = B; LVal.IsOnePastTheEnd = IsOnePastTheEnd; LVal.Offset = O; - LVal.resizePath(Path.size()); - memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry)); LVal.IsNullPtr = IsNullPtr; + LVal.resizePath(Size); + return {LVal.getPath(), Size}; +} + +void APValue::setLValue(LValueBase B, const CharUnits &O, + ArrayRef Path, bool IsOnePastTheEnd, + bool IsNullPtr) { + MutableArrayRef InternalPath = + setLValueUninit(B, O, Path.size(), IsOnePastTheEnd, IsNullPtr); + memcpy(InternalPath.data(), Path.data(), + Path.size() * sizeof(LValuePathEntry)); +} + +void APValue::setUnion(const FieldDecl *Field, const APValue &Value) { + assert(isUnion() && "Invalid accessor"); + ((UnionData *)(char *)Data.buffer)->Field = + Field ? Field->getCanonicalDecl() : nullptr; + *((UnionData*)(char*)Data.buffer)->Value = Value; } const ValueDecl *APValue::getMemberPointerDecl() const { @@ -929,15 +953,27 @@ void APValue::MakeArray(unsigned InitElts, unsigned Size) { Kind = Array; } -void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, - ArrayRef Path) { +MutableArrayRef +setLValueUninit(APValue::LValueBase B, const CharUnits &O, unsigned Size, + bool OnePastTheEnd, bool IsNullPtr); + +MutableArrayRef +APValue::setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember, + unsigned Size) { assert(isAbsent() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; + MemberPointerData *MPD = new ((void *)(char *)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer( Member ? cast(Member->getCanonicalDecl()) : nullptr); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); - MPD->resizePath(Path.size()); + MPD->resizePath(Size); + return {MPD->getPath(), MPD->PathLength}; +} + +void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, + ArrayRef Path) { + MutableArrayRef InternalPath = + setMemberPointerUninit(Member, IsDerivedMember, Path.size()); for (unsigned I = 0; I != Path.size(); ++I) - MPD->getPath()[I] = Path[I]->getCanonicalDecl(); + InternalPath[I] = Path[I]->getCanonicalDecl(); } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2ebc14d6c62c2..1a6a8e77f722b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1005,9 +1005,6 @@ ASTContext::~ASTContext() { for (const auto &Value : ModuleInitializers) Value.second->~PerModuleInitializers(); - - for (APValue *Value : APValueCleanups) - Value->~APValue(); } void ASTContext::setTraversalScope(const std::vector &TopLevelDecls) { @@ -4885,9 +4882,16 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { Arg = TemplateArgument(ArgType); } else if (auto *NTTP = dyn_cast(Param)) { + QualType T = + NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this); + // For class NTTPs, ensure we include the 'const' so the type matches that + // of a real template argument. + // FIXME: It would be more faithful to model this as something like an + // lvalue-to-rvalue conversion applied to a const-qualified lvalue. + if (T->isRecordType()) + T.addConst(); Expr *E = new (*this) DeclRefExpr( - *this, NTTP, /*enclosing*/ false, - NTTP->getType().getNonPackExpansionType().getNonLValueExprType(*this), + *this, NTTP, /*enclosing*/ false, T, Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); if (NTTP->isParameterPack()) @@ -11006,6 +11010,27 @@ ASTContext::getMSGuidDecl(MSGuidDecl::Parts Parts) const { return New; } +TemplateParamObjectDecl * +ASTContext::getTemplateParamObjectDecl(QualType T, const APValue &V) const { + assert(T->isRecordType() && "template param object of unexpected type"); + + // C++ [temp.param]p8: + // [...] a static storage duration object of type 'const T' [...] + T.addConst(); + + llvm::FoldingSetNodeID ID; + TemplateParamObjectDecl::Profile(ID, T, V); + + void *InsertPos; + if (TemplateParamObjectDecl *Existing = + TemplateParamObjectDecls.FindNodeOrInsertPos(ID, InsertPos)) + return Existing; + + TemplateParamObjectDecl *New = TemplateParamObjectDecl::Create(*this, T, V); + TemplateParamObjectDecls.InsertNode(New, InsertPos); + return New; +} + bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { const llvm::Triple &T = getTargetInfo().getTriple(); if (!T.isOSDarwin()) diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 99ce46e83123e..2bc731717b982 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -1834,7 +1834,14 @@ class TemplateDiff { if (VD) { if (AddressOf) OS << "&"; - OS << VD->getName(); + else if (auto *TPO = dyn_cast(VD)) { + // FIXME: Diffing the APValue would be neat. + // FIXME: Suppress this and use the full name of the declaration if the + // parameter is a pointer or reference. + TPO->printAsInit(OS); + return; + } + VD->printName(OS); return; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 100eefa5743c2..49f2f18bf33a1 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -397,6 +397,7 @@ namespace clang { Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To); Expected ImportCastPath(CastExpr *E); + Expected ImportAPValue(const APValue &FromValue); using Designator = DesignatedInitExpr::Designator; @@ -6698,18 +6699,11 @@ ExpectedStmt ASTNodeImporter::VisitAddrLabelExpr(AddrLabelExpr *E) { ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) { Error Err = Error::success(); auto ToSubExpr = importChecked(Err, E->getSubExpr()); + auto ToResult = importChecked(Err, E->getAPValueResult()); if (Err) return std::move(Err); - // TODO : Handle APValue::ValueKind that require importing. - - APValue::ValueKind Kind = E->getResultAPValueKind(); - if (Kind == APValue::Int || Kind == APValue::Float || - Kind == APValue::FixedPoint || Kind == APValue::ComplexFloat || - Kind == APValue::ComplexInt) - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, - E->getAPValueResult()); - return ConstantExpr::Create(Importer.getToContext(), ToSubExpr); + return ConstantExpr::Create(Importer.getToContext(), ToSubExpr, ToResult); } ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Error Err = Error::success(); @@ -7871,7 +7865,8 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - ToType, E->getValueKind(), ToExprLoc, ToParameter, ToReplacement); + ToType, E->getValueKind(), ToExprLoc, ToParameter, + E->isReferenceParameter(), ToReplacement); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -8810,6 +8805,11 @@ ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) { return Imported; } +llvm::Expected ASTImporter::Import(const APValue &FromValue) { + ASTNodeImporter Importer(*this); + return Importer.ImportAPValue(FromValue); +} + Error ASTImporter::ImportDefinition(Decl *From) { ExpectedDecl ToOrErr = Import(From); if (!ToOrErr) @@ -8940,6 +8940,172 @@ Expected ASTImporter::Import(Selector FromSel) { return ToContext.Selectors.getSelector(FromSel.getNumArgs(), Idents.data()); } +llvm::Expected +ASTNodeImporter::ImportAPValue(const APValue &FromValue) { + APValue Result; + llvm::Error Err = llvm::Error::success(); + auto ImportLoop = [&](const APValue *From, APValue *To, unsigned Size) { + for (unsigned Idx = 0; Idx < Size; Idx++) { + APValue Tmp = importChecked(Err, From[Idx]); + To[Idx] = Tmp; + } + }; + switch (FromValue.getKind()) { + case APValue::None: + case APValue::Indeterminate: + case APValue::Int: + case APValue::Float: + case APValue::FixedPoint: + case APValue::ComplexInt: + case APValue::ComplexFloat: + Result = FromValue; + break; + case APValue::Vector: { + Result.MakeVector(); + MutableArrayRef Elts = + Result.setVectorUninit(FromValue.getVectorLength()); + ImportLoop( + ((const APValue::Vec *)(const char *)FromValue.Data.buffer)->Elts, + Elts.data(), FromValue.getVectorLength()); + break; + } + case APValue::Array: + Result.MakeArray(FromValue.getArrayInitializedElts(), + FromValue.getArraySize()); + ImportLoop( + ((const APValue::Arr *)(const char *)FromValue.Data.buffer)->Elts, + ((const APValue::Arr *)(const char *)Result.Data.buffer)->Elts, + FromValue.getArrayInitializedElts()); + break; + case APValue::Struct: + Result.MakeStruct(FromValue.getStructNumBases(), + FromValue.getStructNumFields()); + ImportLoop( + ((const APValue::StructData *)(const char *)FromValue.Data.buffer) + ->Elts, + ((const APValue::StructData *)(const char *)Result.Data.buffer)->Elts, + FromValue.getStructNumBases() + FromValue.getStructNumFields()); + break; + case APValue::Union: { + Result.MakeUnion(); + const Decl *ImpFDecl = importChecked(Err, FromValue.getUnionField()); + APValue ImpValue = importChecked(Err, FromValue.getUnionValue()); + if (Err) + return std::move(Err); + Result.setUnion(cast(ImpFDecl), ImpValue); + break; + } + case APValue::AddrLabelDiff: { + Result.MakeAddrLabelDiff(); + const Expr *ImpLHS = importChecked(Err, FromValue.getAddrLabelDiffLHS()); + const Expr *ImpRHS = importChecked(Err, FromValue.getAddrLabelDiffRHS()); + if (Err) + return std::move(Err); + Result.setAddrLabelDiff(cast(ImpLHS), + cast(ImpRHS)); + break; + } + case APValue::MemberPointer: { + const Decl *ImpMemPtrDecl = + importChecked(Err, FromValue.getMemberPointerDecl()); + if (Err) + return std::move(Err); + MutableArrayRef ToPath = + Result.setMemberPointerUninit( + cast(ImpMemPtrDecl), + FromValue.isMemberPointerToDerivedMember(), + FromValue.getMemberPointerPath().size()); + llvm::ArrayRef FromPath = + Result.getMemberPointerPath(); + for (unsigned Idx = 0; Idx < FromValue.getMemberPointerPath().size(); + Idx++) { + const Decl *ImpDecl = importChecked(Err, FromPath[Idx]); + if (Err) + return std::move(Err); + ToPath[Idx] = cast(ImpDecl->getCanonicalDecl()); + } + break; + } + case APValue::LValue: + APValue::LValueBase Base; + QualType FromElemTy; + if (FromValue.getLValueBase()) { + assert(!FromValue.getLValueBase().is() && + "in C++20 dynamic allocation are transient so they shouldn't " + "appear in the AST"); + if (!FromValue.getLValueBase().is()) { + if (const auto *E = + FromValue.getLValueBase().dyn_cast()) { + FromElemTy = E->getType(); + const Expr *ImpExpr = importChecked(Err, E); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(ImpExpr, + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } else { + FromElemTy = + FromValue.getLValueBase().get()->getType(); + const Decl *ImpDecl = importChecked( + Err, FromValue.getLValueBase().get()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase(cast(ImpDecl), + FromValue.getLValueBase().getCallIndex(), + FromValue.getLValueBase().getVersion()); + } + } else { + FromElemTy = FromValue.getLValueBase().getTypeInfoType(); + QualType ImpTypeInfo = importChecked( + Err, + QualType(FromValue.getLValueBase().get().getType(), + 0)); + QualType ImpType = + importChecked(Err, FromValue.getLValueBase().getTypeInfoType()); + if (Err) + return std::move(Err); + Base = APValue::LValueBase::getTypeInfo( + TypeInfoLValue(ImpTypeInfo.getTypePtr()), ImpType); + } + } + CharUnits Offset = FromValue.getLValueOffset(); + unsigned PathLength = FromValue.getLValuePath().size(); + Result.MakeLValue(); + if (FromValue.hasLValuePath()) { + MutableArrayRef ToPath = Result.setLValueUninit( + Base, Offset, PathLength, FromValue.isLValueOnePastTheEnd(), + FromValue.isNullPointer()); + llvm::ArrayRef FromPath = + FromValue.getLValuePath(); + for (unsigned LoopIdx = 0; LoopIdx < PathLength; LoopIdx++) { + if (FromElemTy->isRecordType()) { + const Decl *FromDecl = + FromPath[LoopIdx].getAsBaseOrMember().getPointer(); + const Decl *ImpDecl = importChecked(Err, FromDecl); + if (Err) + return std::move(Err); + if (auto *RD = dyn_cast(FromDecl)) + FromElemTy = Importer.FromContext.getRecordType(RD); + else + FromElemTy = cast(FromDecl)->getType(); + ToPath[LoopIdx] = APValue::LValuePathEntry(APValue::BaseOrMemberType( + ImpDecl, FromPath[LoopIdx].getAsBaseOrMember().getInt())); + } else { + FromElemTy = + Importer.FromContext.getAsArrayType(FromElemTy)->getElementType(); + ToPath[LoopIdx] = APValue::LValuePathEntry::ArrayIndex( + FromPath[LoopIdx].getAsArrayIndex()); + } + } + } else + Result.setLValue(Base, Offset, APValue::NoLValuePath{}, + FromValue.isNullPointer()); + } + if (Err) + return std::move(Err); + return Result; +} + Expected ASTImporter::HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS, diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index f2502c327a118..0656efae5489f 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -835,6 +835,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ExternCContext: case Decomposition: case MSGuid: + case TemplateParamObject: case UsingDirective: case BuiltinTemplate: diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index d99a9c19c506e..9918377070c3a 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1431,3 +1431,36 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { OS << ">"; } } + +TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C, + QualType T, + const APValue &V) { + DeclContext *DC = C.getTranslationUnitDecl(); + auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +TemplateParamObjectDecl * +TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue()); + C.addDestruction(&TPOD->Value); + return TPOD; +} + +void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS) const { + OS << "