diff --git a/clang/include/clang-c/BuildSystem.h b/clang/include/clang-c/BuildSystem.h index 8f26a861171..4e9f6dee027 100644 --- a/clang/include/clang-c/BuildSystem.h +++ b/clang/include/clang-c/BuildSystem.h @@ -14,13 +14,12 @@ #ifndef LLVM_CLANG_C_BUILDSYSTEM_H #define LLVM_CLANG_C_BUILDSYSTEM_H -#include "clang-c/Platform.h" #include "clang-c/CXErrorCode.h" #include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** * \defgroup BUILD_SYSTEM Build system utilities @@ -148,9 +147,7 @@ CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor); * @} */ -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END #endif /* CLANG_C_BUILD_SYSTEM_H */ diff --git a/clang/include/clang-c/CXCompilationDatabase.h b/clang/include/clang-c/CXCompilationDatabase.h index 2669c1a792c..2b336e5464a 100644 --- a/clang/include/clang-c/CXCompilationDatabase.h +++ b/clang/include/clang-c/CXCompilationDatabase.h @@ -15,12 +15,11 @@ #ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H #define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H -#include "clang-c/Platform.h" #include "clang-c/CXString.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** \defgroup COMPILATIONDB CompilationDatabase functions * \ingroup CINDEX @@ -169,8 +168,7 @@ clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I); * @} */ -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang-c/CXErrorCode.h b/clang/include/clang-c/CXErrorCode.h index fed195ec1f3..b3a0b9d66d5 100644 --- a/clang/include/clang-c/CXErrorCode.h +++ b/clang/include/clang-c/CXErrorCode.h @@ -14,11 +14,10 @@ #ifndef LLVM_CLANG_C_CXERRORCODE_H #define LLVM_CLANG_C_CXERRORCODE_H +#include "clang-c/ExternC.h" #include "clang-c/Platform.h" -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** * Error codes returned by libclang routines. @@ -57,8 +56,7 @@ enum CXErrorCode { CXError_ASTReadError = 4 }; -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang-c/CXString.h b/clang/include/clang-c/CXString.h index 1eb3442ccb2..f117010c71a 100644 --- a/clang/include/clang-c/CXString.h +++ b/clang/include/clang-c/CXString.h @@ -14,11 +14,10 @@ #ifndef LLVM_CLANG_C_CXSTRING_H #define LLVM_CLANG_C_CXSTRING_H +#include "clang-c/ExternC.h" #include "clang-c/Platform.h" -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** * \defgroup CINDEX_STRING String manipulation routines @@ -64,8 +63,7 @@ CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set); * @} */ -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang-c/Documentation.h b/clang/include/clang-c/Documentation.h index 4af8c93a367..5bece2cb675 100644 --- a/clang/include/clang-c/Documentation.h +++ b/clang/include/clang-c/Documentation.h @@ -15,11 +15,10 @@ #ifndef LLVM_CLANG_C_DOCUMENTATION_H #define LLVM_CLANG_C_DOCUMENTATION_H +#include "clang-c/ExternC.h" #include "clang-c/Index.h" -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** * \defgroup CINDEX_COMMENT Comment introspection @@ -182,7 +181,12 @@ enum CXCommentInlineCommandRenderKind { * Command argument should be rendered emphasized (typically italic * font). */ - CXCommentInlineCommandRenderKind_Emphasized + CXCommentInlineCommandRenderKind_Emphasized, + + /** + * Command argument should not be rendered (since it only defines an anchor). + */ + CXCommentInlineCommandRenderKind_Anchor }; /** @@ -545,10 +549,7 @@ CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); * @} */ - -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END #endif /* CLANG_C_DOCUMENTATION_H */ diff --git a/clang/include/clang-c/ExternC.h b/clang/include/clang-c/ExternC.h new file mode 100644 index 00000000000..384f24d47b0 --- /dev/null +++ b/clang/include/clang-c/ExternC.h @@ -0,0 +1,39 @@ +/*===- clang-c/ExternC.h - Wrapper for 'extern "C"' ---------------*- 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 an 'extern "C"' wrapper. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_CLANG_C_EXTERN_C_H +#define LLVM_CLANG_C_EXTERN_C_H + +#ifdef __clang__ +#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wstrict-prototypes\"") +#define LLVM_CLANG_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop") +#else +#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_STRICT_PROTOTYPES_END +#endif + +#ifdef __cplusplus +#define LLVM_CLANG_C_EXTERN_C_BEGIN \ + extern "C" { \ + LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_EXTERN_C_END \ + LLVM_CLANG_C_STRICT_PROTOTYPES_END \ + } +#else +#define LLVM_CLANG_C_EXTERN_C_BEGIN LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN +#define LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_STRICT_PROTOTYPES_END +#endif + +#endif diff --git a/clang/include/clang-c/FatalErrorHandler.h b/clang/include/clang-c/FatalErrorHandler.h index ce8ff2cae73..22f34fa815c 100644 --- a/clang/include/clang-c/FatalErrorHandler.h +++ b/clang/include/clang-c/FatalErrorHandler.h @@ -10,9 +10,9 @@ #ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H #define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H -#ifdef __cplusplus -extern "C" { -#endif +#include "clang-c/ExternC.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN /** * Installs error handler that prints error message to stderr and calls abort(). @@ -27,7 +27,6 @@ void clang_install_aborting_llvm_fatal_error_handler(void); */ void clang_uninstall_llvm_fatal_error_handler(void); -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 22689350543..b653995ebbd 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -18,10 +18,11 @@ #include -#include "clang-c/Platform.h" +#include "clang-c/BuildSystem.h" #include "clang-c/CXErrorCode.h" #include "clang-c/CXString.h" -#include "clang-c/BuildSystem.h" +#include "clang-c/ExternC.h" +#include "clang-c/Platform.h" /** * The version constants for the libclang API. @@ -51,9 +52,7 @@ CINDEX_VERSION_MAJOR, \ CINDEX_VERSION_MINOR) -#ifdef __cplusplus -extern "C" { -#endif +LLVM_CLANG_C_EXTERN_C_BEGIN /** \defgroup CINDEX libclang: C Interface to Clang * @@ -2567,8 +2566,15 @@ enum CXCursorKind { */ CXCursor_OMPMasterTaskLoopSimdDirective = 283, + /** OpenMP parallel master taskloop simd directive. + */ + CXCursor_OMPParallelMasterTaskLoopSimdDirective = 284, - CXCursor_LastStmt = CXCursor_OMPMasterTaskLoopSimdDirective, + /** OpenMP parallel master directive. + */ + CXCursor_OMPParallelMasterDirective = 285, + + CXCursor_LastStmt = CXCursor_OMPParallelMasterDirective, /** * Cursor that represents the translation unit itself. @@ -6771,7 +6777,6 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T, * @} */ -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang-c/Platform.h b/clang/include/clang-c/Platform.h index 5284b533253..3bb66bb0df4 100644 --- a/clang/include/clang-c/Platform.h +++ b/clang/include/clang-c/Platform.h @@ -14,9 +14,9 @@ #ifndef LLVM_CLANG_C_PLATFORM_H #define LLVM_CLANG_C_PLATFORM_H -#ifdef __cplusplus -extern "C" { -#endif +#include "clang-c/ExternC.h" + +LLVM_CLANG_C_EXTERN_C_BEGIN /* MSVC DLL import/export. */ #ifdef _MSC_VER @@ -39,7 +39,6 @@ extern "C" { #endif #endif -#ifdef __cplusplus -} -#endif +LLVM_CLANG_C_EXTERN_C_END + #endif diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h new file mode 100644 index 00000000000..896d857d8c9 --- /dev/null +++ b/clang/include/clang/AST/ASTConcept.h @@ -0,0 +1,177 @@ +//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file provides AST data structures related to concepts. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_ASTCONCEPT_H +#define LLVM_CLANG_AST_ASTCONCEPT_H +#include "clang/AST/Expr.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include +#include +namespace clang { +class ConceptDecl; + +/// \brief The result of a constraint satisfaction check, containing the +/// necessary information to diagnose an unsatisfied constraint. +struct ConstraintSatisfaction { + using SubstitutionDiagnostic = std::pair; + using Detail = llvm::PointerUnion; + + bool IsSatisfied = false; + + /// \brief Pairs of unsatisfied atomic constraint expressions along with the + /// substituted constraint expr, if the template arguments could be + /// substituted into them, or a diagnostic if substitution resulted in an + /// invalid expression. + llvm::SmallVector, 4> Details; + + // This can leak if used in an AST node, use ASTConstraintSatisfaction + // instead. + void *operator new(size_t bytes, ASTContext &C) = delete; +}; + +/// Pairs of unsatisfied atomic constraint expressions along with the +/// substituted constraint expr, if the template arguments could be +/// substituted into them, or a diagnostic if substitution resulted in +/// an invalid expression. +using UnsatisfiedConstraintRecord = + std::pair *>>; + +/// \brief The result of a constraint satisfaction check, containing the +/// necessary information to diagnose an unsatisfied constraint. +/// +/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction. +struct ASTConstraintSatisfaction final : + llvm::TrailingObjects { + std::size_t NumRecords; + bool IsSatisfied : 1; + + const UnsatisfiedConstraintRecord *begin() const { + return getTrailingObjects(); + } + + const UnsatisfiedConstraintRecord *end() const { + return getTrailingObjects() + NumRecords; + } + + ASTConstraintSatisfaction(const ASTContext &C, + const ConstraintSatisfaction &Satisfaction); + + static ASTConstraintSatisfaction * + Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); +}; + +/// \brief Common data class for constructs that reference concepts with +/// template arguments. +class ConceptReference { +protected: + // \brief The optional nested name specifier used when naming the concept. + NestedNameSpecifierLoc NestedNameSpec; + + /// \brief The location of the template keyword, if specified when naming the + /// concept. + SourceLocation TemplateKWLoc; + + /// \brief The concept name used. + DeclarationNameInfo ConceptName; + + /// \brief The declaration found by name lookup when the expression was + /// created. + /// Can differ from NamedConcept when, for example, the concept was found + /// through a UsingShadowDecl. + NamedDecl *FoundDecl; + + /// \brief The concept named. + ConceptDecl *NamedConcept; + + /// \brief The template argument list source info used to specialize the + /// concept. + const ASTTemplateArgumentListInfo *ArgsAsWritten; + +public: + + ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten) : + NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), + ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), + NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} + + ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(), + FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return NestedNameSpec; + } + + const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; } + + SourceLocation getConceptNameLoc() const { + return getConceptNameInfo().getLoc(); + } + + SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } + + NamedDecl *getFoundDecl() const { + return FoundDecl; + } + + ConceptDecl *getNamedConcept() const { + return NamedConcept; + } + + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + + /// \brief Whether or not template arguments were explicitly specified in the + /// concept reference (they might not be in type constraints, for example) + bool hasExplicitTemplateArgs() const { + return ArgsAsWritten != nullptr; + } +}; + +class TypeConstraint : public ConceptReference { + /// \brief The immediately-declared constraint expression introduced by this + /// type-constraint. + Expr *ImmediatelyDeclaredConstraint = nullptr; + +public: + TypeConstraint(NestedNameSpecifierLoc NNS, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + Expr *ImmediatelyDeclaredConstraint) : + ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo, + FoundDecl, NamedConcept, ArgsAsWritten), + ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {} + + /// \brief Get the immediately-declared constraint expression introduced by + /// this type-constraint, that is - the constraint expression that is added to + /// the associated constraints of the enclosing declaration in practice. + Expr *getImmediatelyDeclaredConstraint() const { + return ImmediatelyDeclaredConstraint; + } + + void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; +}; + +} // clang + +#endif // LLVM_CLANG_AST_ASTCONCEPT_H \ No newline at end of file diff --git a/clang/include/clang/AST/ASTConsumer.h b/clang/include/clang/AST/ASTConsumer.h index dc216a89c20..ecdd8e873e1 100644 --- a/clang/include/clang/AST/ASTConsumer.h +++ b/clang/include/clang/AST/ASTConsumer.h @@ -102,6 +102,11 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// CompleteExternalDeclaration - Callback invoked at the end of a translation + /// unit to notify the consumer that the given external declaration should be + /// completed. + virtual void CompleteExternalDeclaration(VarDecl *D) {} + /// Callback invoked when an MSInheritanceAttr has been attached to a /// CXXRecordDecl. virtual void AssignInheritanceModel(CXXRecordDecl *RD) {} diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5e2f4031d96..fb269cef1ce 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -22,7 +22,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/Expr.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -96,6 +95,7 @@ class CXXRecordDecl; class DiagnosticsEngine; class Expr; class FixedPointSemantics; +class GlobalDecl; class MangleContext; class MangleNumberingContext; class MaterializeTemporaryExpr; @@ -113,9 +113,11 @@ class ObjCPropertyDecl; class ObjCPropertyImplDecl; class ObjCProtocolDecl; class ObjCTypeParamDecl; +struct ParsedTargetAttr; class Preprocessor; class Stmt; class StoredDeclsMap; +class TargetAttr; class TemplateDecl; class TemplateParameterList; class TemplateTemplateParmDecl; @@ -124,6 +126,7 @@ class UnresolvedSetIterator; class UsingShadowDecl; class VarTemplateDecl; class VTableContextBase; +struct BlockVarCopyInit; namespace Builtin { @@ -145,6 +148,10 @@ class Context; } // namespace interp +namespace serialization { +template class AbstractTypeReader; +} // namespace serialization + struct TypeInfo { uint64_t Width = 0; unsigned Align = 0; @@ -158,22 +165,6 @@ struct TypeInfo { /// Holds long-lived AST nodes (such as types and decls) that can be /// referred to throughout the semantic analysis of a file. class ASTContext : public RefCountedBase { -public: - /// Copy initialization expr of a __block variable and a boolean flag that - /// indicates whether the expression can throw. - struct BlockVarCopyInit { - BlockVarCopyInit() = default; - BlockVarCopyInit(Expr *CopyExpr, bool CanThrow) - : ExprAndFlag(CopyExpr, CanThrow) {} - void setExprAndFlag(Expr *CopyExpr, bool CanThrow) { - ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow); - } - Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); } - bool canThrow() const { return ExprAndFlag.getInt(); } - llvm::PointerIntPair ExprAndFlag; - }; - -private: friend class NestedNameSpecifier; mutable SmallVector Types; @@ -272,12 +263,6 @@ private: /// Mapping from __block VarDecls to BlockVarCopyInit. llvm::DenseMap BlockVarCopyInits; - /// Mapping from materialized temporaries with static storage duration - /// that appear in constant initializers to their evaluated values. These are - /// allocated in a std::map because their address must be stable. - llvm::DenseMap - MaterializedTemporaryValues; - /// Used to cleanups APValues stored in the AST. mutable llvm::SmallVector APValueCleanups; @@ -298,12 +283,16 @@ private: TemplateTemplateParmDecl *getParam() const { return Parm; } - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); } + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) { + Profile(ID, C, Parm); + } static void Profile(llvm::FoldingSetNodeID &ID, + const ASTContext &C, TemplateTemplateParmDecl *Parm); }; - mutable llvm::FoldingSet + mutable llvm::ContextualFoldingSet CanonTemplateTemplateParms; TemplateTemplateParmDecl * @@ -435,6 +424,7 @@ private: friend class ASTDeclReader; friend class ASTReader; friend class ASTWriter; + template friend class serialization::AbstractTypeReader; friend class CXXRecordDecl; /// A mapping to contain the template or declaration that @@ -575,7 +565,17 @@ private: clang::PrintingPolicy PrintingPolicy; std::unique_ptr InterpContext; + ast_type_traits::TraversalKind Traversal = ast_type_traits::TK_AsIs; + public: + ast_type_traits::TraversalKind getTraversalKind() const { return Traversal; } + void setTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; } + + const Expr *traverseIgnored(const Expr *E) const; + Expr *traverseIgnored(Expr *E) const; + ast_type_traits::DynTypedNode + traverseIgnored(const ast_type_traits::DynTypedNode &N) const; + IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; @@ -1162,6 +1162,10 @@ public: /// attribute. QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const; + /// Remove the existing address space on the type if it is a pointer size + /// address space and return the type with qualifiers intact. + QualType removePtrSizeAddrSpace(QualType T) const; + /// Return the uniqued reference to the type for a \c restrict /// qualified type. /// @@ -1216,6 +1220,15 @@ public: const FunctionProtoType::ExceptionSpecInfo &ESI, bool AsWritten = false); + /// Get a function type and produce the equivalent function type where + /// pointer size address spaces in the return type and parameter tyeps are + /// replaced with the default address space. + QualType getFunctionTypeWithoutPtrSizes(QualType T); + + /// Determine whether two function types are the same, ignoring pointer sizes + /// in the return type and parameter types. + bool hasSameFunctionTypeIgnoringPtrSizes(QualType T, QualType U); + /// Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; @@ -2827,16 +2840,20 @@ public: /// index of the parameter when it exceeds the size of the normal bitfield. unsigned getParameterIndex(const ParmVarDecl *D) const; - /// Get the storage for the constant value of a materialized temporary - /// of static storage duration. - APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, - bool MayCreate); - /// Return a string representing the human readable name for the specified /// function declaration or file name. Used by SourceLocExpr and /// PredefinedExpr to cache evaluated results. StringLiteral *getPredefinedStringLiteralFromCache(StringRef Key) const; + /// Parses the target attributes passed in, and returns only the ones that are + /// valid feature names. + ParsedTargetAttr filterFunctionTargetAttrs(const TargetAttr *TD) const; + + void getFunctionFeatureMap(llvm::StringMap &FeatureMap, + const FunctionDecl *) const; + void getFunctionFeatureMap(llvm::StringMap &FeatureMap, + GlobalDecl GD) const; + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// @@ -3007,7 +3024,7 @@ private: std::vector TraversalScope; class ParentMap; - std::unique_ptr Parents; + std::map> Parents; std::unique_ptr VTContext; @@ -3051,6 +3068,22 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { return Ctx.Selectors.getSelector(1, &II); } +class TraversalKindScope { + ASTContext &Ctx; + ast_type_traits::TraversalKind TK = ast_type_traits::TK_AsIs; + +public: + TraversalKindScope(ASTContext &Ctx, + llvm::Optional ScopeTK) + : Ctx(Ctx) { + TK = Ctx.getTraversalKind(); + if (ScopeTK) + Ctx.setTraversalKind(*ScopeTK); + } + + ~TraversalKindScope() { Ctx.setTraversalKind(TK); } +}; + } // namespace clang // operator new and delete aren't allowed inside namespaces. diff --git a/clang/include/clang/AST/ASTFwd.h b/clang/include/clang/AST/ASTFwd.h index 25c32148544..5a891817b33 100644 --- a/clang/include/clang/AST/ASTFwd.h +++ b/clang/include/clang/AST/ASTFwd.h @@ -26,6 +26,10 @@ class Type; #define TYPE(DERIVED, BASE) class DERIVED##Type; #include "clang/AST/TypeNodes.inc" class CXXCtorInitializer; +class OMPClause; +#define OPENMP_CLAUSE(KIND, CLASSNAME) class CLASSNAME; +#include "clang/Basic/OpenMPKinds.def" + } // end namespace clang diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index c82dcab35db..490b34bf95e 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -60,8 +60,12 @@ class TypeSourceInfo; static char ID; - ImportError() : Error(Unknown) { } - ImportError(const ImportError &Other) : Error(Other.Error) { } + ImportError() : Error(Unknown) {} + ImportError(const ImportError &Other) : Error(Other.Error) {} + ImportError &operator=(const ImportError &Other) { + Error = Other.Error; + return *this; + } ImportError(ErrorKind Error) : Error(Error) { } std::string toString() const; diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h index c1153168e41..6fd82d6af49 100644 --- a/clang/include/clang/AST/ASTLambda.h +++ b/clang/include/clang/AST/ASTLambda.h @@ -64,6 +64,17 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { dyn_cast(DC)); } +inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( + DeclContext *DC) { + CXXMethodDecl *MD = dyn_cast(DC); + if (!MD) return false; + const CXXRecordDecl *LambdaClass = MD->getParent(); + if (LambdaClass && LambdaClass->isGenericLambda()) + return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) && + MD->isFunctionTemplateSpecialization(); + return false; +} + // This returns the parent DeclContext ensuring that the correct // parent DeclContext is returned for Lambdas diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 0bb2aad553f..e0ebb020e69 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -65,6 +65,9 @@ class ASTNodeTraverser /// not already been loaded. bool Deserialize = false; + ast_type_traits::TraversalKind Traversal = + ast_type_traits::TraversalKind::TK_AsIs; + NodeDelegateType &getNodeDelegate() { return getDerived().doGetNodeDelegate(); } @@ -74,6 +77,8 @@ public: void setDeserialize(bool D) { Deserialize = D; } bool getDeserialize() const { return Deserialize; } + void SetTraversalKind(ast_type_traits::TraversalKind TK) { Traversal = TK; } + void Visit(const Decl *D) { getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(D); @@ -97,8 +102,23 @@ public: }); } - void Visit(const Stmt *S, StringRef Label = {}) { + void Visit(const Stmt *Node, StringRef Label = {}) { getNodeDelegate().AddChild(Label, [=] { + const Stmt *S = Node; + + if (auto *E = dyn_cast_or_null(S)) { + switch (Traversal) { + case ast_type_traits::TK_AsIs: + break; + case ast_type_traits::TK_IgnoreImplicitCastsAndParentheses: + S = E->IgnoreParenImpCasts(); + break; + case ast_type_traits::TK_IgnoreUnlessSpelledInSource: + S = E->IgnoreUnlessSpelledInSource(); + break; + } + } + getNodeDelegate().Visit(S); if (!S) { @@ -108,9 +128,12 @@ public: ConstStmtVisitor::Visit(S); // Some statements have custom mechanisms for dumping their children. - if (isa(S) || isa(S)) { + if (isa(S) || isa(S)) + return; + + if (isa(S) && + Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) return; - } for (const Stmt *SubStmt : S->children()) Visit(SubStmt); @@ -361,6 +384,9 @@ public: for (const auto *Parameter : D->parameters()) Visit(Parameter); + if (const Expr *TRC = D->getTrailingRequiresClause()) + Visit(TRC); + if (const auto *C = dyn_cast(D)) for (const auto *I : C->inits()) Visit(I); @@ -511,6 +537,10 @@ public: } void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (const auto *TC = D->getTypeConstraint()) + if (TC->hasExplicitTemplateArgs()) + for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments()) + dumpTemplateArgumentLoc(ArgLoc); if (D->hasDefaultArgument()) Visit(D->getDefaultArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), @@ -518,6 +548,8 @@ public: } void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + if (const auto *TC = D->getPlaceholderTypeConstraint()) + Visit(TC->getImmediatelyDeclaredConstraint()); if (D->hasDefaultArgument()) Visit(D->getDefaultArgument(), SourceRange(), D->getDefaultArgStorage().getInheritedFrom(), @@ -620,13 +652,29 @@ public: Visit(E->getControllingExpr()); Visit(E->getControllingExpr()->getType()); // FIXME: remove - for (const auto &Assoc : E->associations()) { + for (const auto Assoc : E->associations()) { Visit(Assoc); } } void VisitLambdaExpr(const LambdaExpr *Node) { - Visit(Node->getLambdaClass()); + if (Traversal == ast_type_traits::TK_IgnoreUnlessSpelledInSource) { + for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { + const auto *C = Node->capture_begin() + I; + if (!C->isExplicit()) + continue; + if (Node->isInitCapture(C)) + Visit(C->getCapturedVar()); + else + Visit(Node->capture_init_begin()[I]); + } + dumpTemplateParameters(Node->getTemplateParameterList()); + for (const auto *P : Node->getCallOperator()->parameters()) + Visit(P); + Visit(Node->getBody()); + } else { + return Visit(Node->getLambdaClass()); + } } void VisitSizeOfPackExpr(const SizeOfPackExpr *Node) { diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index dd4ead2f0c2..1a12281d039 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -16,10 +16,7 @@ #define LLVM_CLANG_AST_ASTTYPETRAITS_H #include "clang/AST/ASTFwd.h" -#include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/OpenMPClause.h" -#include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" @@ -46,7 +43,10 @@ enum TraversalKind { /// Will not traverse implicit casts and parentheses. /// Corresponds to Expr::IgnoreParenImpCasts() - TK_IgnoreImplicitCastsAndParentheses + TK_IgnoreImplicitCastsAndParentheses, + + /// Ignore AST nodes not written in the source + TK_IgnoreUnlessSpelledInSource }; /// Kind identifier. diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h new file mode 100644 index 00000000000..d7b3a9da88e --- /dev/null +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -0,0 +1,263 @@ +//==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_AST_ABSTRACTBASICREADER_H +#define CLANG_AST_ABSTRACTBASICREADER_H + +#include "clang/AST/DeclTemplate.h" + +namespace clang { +namespace serialization { + +template +inline T makeNullableFromOptional(const Optional &value) { + return (value ? *value : T()); +} + +template +inline T *makePointerFromOptional(Optional value) { + return (value ? *value : nullptr); +} + +// PropertyReader is a class concept that requires the following method: +// BasicReader find(llvm::StringRef propertyName); +// where BasicReader is some class conforming to the BasicReader concept. +// An abstract AST-node reader is created with a PropertyReader and +// performs a sequence of calls like so: +// propertyReader.find(propertyName).read##TypeName() +// to read the properties of the node it is deserializing. + +// BasicReader is a class concept that requires methods like: +// ValueType read##TypeName(); +// where TypeName is the name of a PropertyType node from PropertiesBase.td +// and ValueType is the corresponding C++ type name. The read method may +// require one or more buffer arguments. +// +// In addition to the concrete type names, BasicReader is expected to +// implement these methods: +// +// template +// void writeEnum(T value); +// +// Reads an enum value from the current property. EnumType will always +// be an enum type. Only necessary if the BasicReader doesn't provide +// type-specific readers for all the enum types. +// +// template +// Optional writeOptional(); +// +// Reads an optional value from the current property. +// +// template +// ArrayRef readArray(llvm::SmallVectorImpl &buffer); +// +// Reads an array of values from the current property. +// +// PropertyReader readObject(); +// +// Reads an object from the current property; the returned property +// reader will be subjected to a sequence of property reads and then +// discarded before any other properties are reader from the "outer" +// property reader (which need not be the same type). The sub-reader +// will be used as if with the following code: +// +// { +// auto &&widget = W.find("widget").readObject(); +// auto kind = widget.find("kind").readWidgetKind(); +// auto declaration = widget.find("declaration").readDeclRef(); +// return Widget(kind, declaration); +// } + +// ReadDispatcher does type-based forwarding to one of the read methods +// on the BasicReader passed in: +// +// template +// struct ReadDispatcher { +// template +// static ValueType read(BasicReader &R, BufferTypes &&...); +// }; + +// BasicReaderBase provides convenience implementations of the read methods +// for EnumPropertyType and SubclassPropertyType types that just defer to +// the "underlying" implementations (for UInt32 and the base class, +// respectively). +// +// template +// class BasicReaderBase { +// protected: +// BasicReaderBase(ASTContext &ctx); +// Impl &asImpl(); +// public: +// ASTContext &getASTContext(); +// ... +// }; + +// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp. +#include "clang/AST/AbstractBasicReader.inc" + +/// DataStreamBasicReader provides convenience implementations for many +/// BasicReader methods based on the assumption that the +/// ultimate reader implementation is based on a variable-length stream +/// of unstructured data (like Clang's module files). It is designed +/// to pair with DataStreamBasicWriter. +/// +/// This class can also act as a PropertyReader, implementing find("...") +/// by simply forwarding to itself. +/// +/// Unimplemented methods: +/// readBool +/// readUInt32 +/// readUInt64 +/// readIdentifier +/// readSelector +/// readSourceLocation +/// readQualType +/// readStmtRef +/// readDeclRef +template +class DataStreamBasicReader : public BasicReaderBase { +protected: + using BasicReaderBase::asImpl; + DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase(ctx) {} + +public: + using BasicReaderBase::getASTContext; + + /// Implement property-find by ignoring it. We rely on properties being + /// serialized and deserialized in a reliable order instead. + Impl &find(const char *propertyName) { + return asImpl(); + } + + template + T readEnum() { + return T(asImpl().readUInt32()); + } + + // Implement object reading by forwarding to this, collapsing the + // structure into a single data stream. + Impl &readObject() { return asImpl(); } + + template + llvm::ArrayRef readArray(llvm::SmallVectorImpl &buffer) { + assert(buffer.empty()); + + uint32_t size = asImpl().readUInt32(); + buffer.reserve(size); + + for (uint32_t i = 0; i != size; ++i) { + buffer.push_back(ReadDispatcher::read(asImpl())); + } + return buffer; + } + + template + llvm::Optional readOptional(Args &&...args) { + return UnpackOptionalValue::unpack( + ReadDispatcher::read(asImpl(), std::forward(args)...)); + } + + llvm::APSInt readAPSInt() { + bool isUnsigned = asImpl().readBool(); + llvm::APInt value = asImpl().readAPInt(); + return llvm::APSInt(std::move(value), isUnsigned); + } + + llvm::APInt readAPInt() { + unsigned bitWidth = asImpl().readUInt32(); + unsigned numWords = llvm::APInt::getNumWords(bitWidth); + llvm::SmallVector data; + for (uint32_t i = 0; i != numWords; ++i) + data.push_back(asImpl().readUInt64()); + return llvm::APInt(bitWidth, numWords, &data[0]); + } + + Qualifiers readQualifiers() { + static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t), + "update this if the value size changes"); + uint32_t value = asImpl().readUInt32(); + return Qualifiers::fromOpaqueValue(value); + } + + FunctionProtoType::ExceptionSpecInfo + readExceptionSpecInfo(llvm::SmallVectorImpl &buffer) { + FunctionProtoType::ExceptionSpecInfo esi; + esi.Type = ExceptionSpecificationType(asImpl().readUInt32()); + if (esi.Type == EST_Dynamic) { + esi.Exceptions = asImpl().template readArray(buffer); + } else if (isComputedNoexcept(esi.Type)) { + esi.NoexceptExpr = asImpl().readExprRef(); + } else if (esi.Type == EST_Uninstantiated) { + esi.SourceDecl = asImpl().readFunctionDeclRef(); + esi.SourceTemplate = asImpl().readFunctionDeclRef(); + } else if (esi.Type == EST_Unevaluated) { + esi.SourceDecl = asImpl().readFunctionDeclRef(); + } + return esi; + } + + FunctionProtoType::ExtParameterInfo readExtParameterInfo() { + static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue()) + <= sizeof(uint32_t), + "opaque value doesn't fit into uint32_t"); + uint32_t value = asImpl().readUInt32(); + return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value); + } + + NestedNameSpecifier *readNestedNameSpecifier() { + auto &ctx = getASTContext(); + + // We build this up iteratively. + NestedNameSpecifier *cur = nullptr; + + uint32_t depth = asImpl().readUInt32(); + for (uint32_t i = 0; i != depth; ++i) { + auto kind = asImpl().readNestedNameSpecifierKind(); + switch (kind) { + case NestedNameSpecifier::Identifier: + cur = NestedNameSpecifier::Create(ctx, cur, + asImpl().readIdentifier()); + continue; + + case NestedNameSpecifier::Namespace: + cur = NestedNameSpecifier::Create(ctx, cur, + asImpl().readNamespaceDeclRef()); + continue; + + case NestedNameSpecifier::NamespaceAlias: + cur = NestedNameSpecifier::Create(ctx, cur, + asImpl().readNamespaceAliasDeclRef()); + continue; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + cur = NestedNameSpecifier::Create(ctx, cur, + kind == NestedNameSpecifier::TypeSpecWithTemplate, + asImpl().readQualType().getTypePtr()); + continue; + + case NestedNameSpecifier::Global: + cur = NestedNameSpecifier::GlobalSpecifier(ctx); + continue; + + case NestedNameSpecifier::Super: + cur = NestedNameSpecifier::SuperSpecifier(ctx, + asImpl().readCXXRecordDeclRef()); + continue; + } + llvm_unreachable("bad nested name specifier kind"); + } + + return cur; + } +}; + +} // end namespace serialization +} // end namespace clang + +#endif diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h new file mode 100644 index 00000000000..0a6730c86bb --- /dev/null +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -0,0 +1,243 @@ +//==--- AbstractBasicWriter.h - Abstract basic value serialization --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_AST_ABSTRACTBASICWRITER_H +#define CLANG_AST_ABSTRACTBASICWRITER_H + +#include "clang/AST/DeclTemplate.h" + +namespace clang { +namespace serialization { + +template +inline llvm::Optional makeOptionalFromNullable(const T &value) { + return (value.isNull() + ? llvm::Optional() + : llvm::Optional(value)); +} + +template +inline llvm::Optional makeOptionalFromPointer(T *value) { + return (value ? llvm::Optional(value) : llvm::Optional()); +} + +// PropertyWriter is a class concept that requires the following method: +// BasicWriter find(llvm::StringRef propertyName); +// where BasicWriter is some class conforming to the BasicWriter concept. +// An abstract AST-node writer is created with a PropertyWriter and +// performs a sequence of calls like so: +// propertyWriter.find(propertyName).write##TypeName(value) +// to write the properties of the node it is serializing. + +// BasicWriter is a class concept that requires methods like: +// void write##TypeName(ValueType value); +// where TypeName is the name of a PropertyType node from PropertiesBase.td +// and ValueType is the corresponding C++ type name. +// +// In addition to the concrete property types, BasicWriter is expected +// to implement these methods: +// +// template +// void writeEnum(T value); +// +// Writes an enum value as the current property. EnumType will always +// be an enum type. Only necessary if the BasicWriter doesn't provide +// type-specific writers for all the enum types. +// +// template +// void writeOptional(Optional value); +// +// Writes an optional value as the current property. +// +// template +// void writeArray(ArrayRef value); +// +// Writes an array of values as the current property. +// +// PropertyWriter writeObject(); +// +// Writes an object as the current property; the returned property +// writer will be subjected to a sequence of property writes and then +// discarded before any other properties are written to the "outer" +// property writer (which need not be the same type). The sub-writer +// will be used as if with the following code: +// +// { +// auto &&widget = W.find("widget").writeObject(); +// widget.find("kind").writeWidgetKind(...); +// widget.find("declaration").writeDeclRef(...); +// } + +// WriteDispatcher is a template which does type-based forwarding to one +// of the write methods of the BasicWriter passed in: +// +// template +// struct WriteDispatcher { +// template +// static void write(BasicWriter &W, ValueType value); +// }; + +// BasicWriterBase provides convenience implementations of the write +// methods for EnumPropertyType and SubclassPropertyType types that just +// defer to the "underlying" implementations (for UInt32 and the base class, +// respectively). +// +// template +// class BasicWriterBase { +// protected: +// Impl &asImpl(); +// public: +// ... +// }; + +// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp. +#include "clang/AST/AbstractBasicWriter.inc" + +/// DataStreamBasicWriter provides convenience implementations for many +/// BasicWriter methods based on the assumption that the +/// ultimate writer implementation is based on a variable-length stream +/// of unstructured data (like Clang's module files). It is designed +/// to pair with DataStreamBasicReader. +/// +/// This class can also act as a PropertyWriter, implementing find("...") +/// by simply forwarding to itself. +/// +/// Unimplemented methods: +/// writeBool +/// writeUInt32 +/// writeUInt64 +/// writeIdentifier +/// writeSelector +/// writeSourceLocation +/// writeQualType +/// writeStmtRef +/// writeDeclRef +template +class DataStreamBasicWriter : public BasicWriterBase { +protected: + using BasicWriterBase::asImpl; + +public: + /// Implement property-find by ignoring it. We rely on properties being + /// serialized and deserialized in a reliable order instead. + Impl &find(const char *propertyName) { + return asImpl(); + } + + // Implement object writing by forwarding to this, collapsing the + // structure into a single data stream. + Impl &writeObject() { return asImpl(); } + + template + void writeEnum(T value) { + asImpl().writeUInt32(uint32_t(value)); + } + + template + void writeArray(llvm::ArrayRef array) { + asImpl().writeUInt32(array.size()); + for (const T &elt : array) { + WriteDispatcher::write(asImpl(), elt); + } + } + + template + void writeOptional(llvm::Optional value) { + WriteDispatcher::write(asImpl(), PackOptionalValue::pack(value)); + } + + void writeAPSInt(const llvm::APSInt &value) { + asImpl().writeBool(value.isUnsigned()); + asImpl().writeAPInt(value); + } + + void writeAPInt(const llvm::APInt &value) { + asImpl().writeUInt32(value.getBitWidth()); + const uint64_t *words = value.getRawData(); + for (size_t i = 0, e = value.getNumWords(); i != e; ++i) + asImpl().writeUInt64(words[i]); + } + + void writeQualifiers(Qualifiers value) { + static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t), + "update this if the value size changes"); + asImpl().writeUInt32(value.getAsOpaqueValue()); + } + + void writeExceptionSpecInfo( + const FunctionProtoType::ExceptionSpecInfo &esi) { + asImpl().writeUInt32(uint32_t(esi.Type)); + if (esi.Type == EST_Dynamic) { + asImpl().writeArray(esi.Exceptions); + } else if (isComputedNoexcept(esi.Type)) { + asImpl().writeExprRef(esi.NoexceptExpr); + } else if (esi.Type == EST_Uninstantiated) { + asImpl().writeDeclRef(esi.SourceDecl); + asImpl().writeDeclRef(esi.SourceTemplate); + } else if (esi.Type == EST_Unevaluated) { + asImpl().writeDeclRef(esi.SourceDecl); + } + } + + void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) { + static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t), + "opaque value doesn't fit into uint32_t"); + asImpl().writeUInt32(epi.getOpaqueValue()); + } + + void writeNestedNameSpecifier(NestedNameSpecifier *NNS) { + // Nested name specifiers usually aren't too long. I think that 8 would + // typically accommodate the vast majority. + SmallVector nestedNames; + + // Push each of the NNS's onto a stack for serialization in reverse order. + while (NNS) { + nestedNames.push_back(NNS); + NNS = NNS->getPrefix(); + } + + asImpl().writeUInt32(nestedNames.size()); + while (!nestedNames.empty()) { + NNS = nestedNames.pop_back_val(); + NestedNameSpecifier::SpecifierKind kind = NNS->getKind(); + asImpl().writeNestedNameSpecifierKind(kind); + switch (kind) { + case NestedNameSpecifier::Identifier: + asImpl().writeIdentifier(NNS->getAsIdentifier()); + continue; + + case NestedNameSpecifier::Namespace: + asImpl().writeNamespaceDeclRef(NNS->getAsNamespace()); + continue; + + case NestedNameSpecifier::NamespaceAlias: + asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias()); + continue; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + asImpl().writeQualType(QualType(NNS->getAsType(), 0)); + continue; + + case NestedNameSpecifier::Global: + // Don't need to write an associated value. + continue; + + case NestedNameSpecifier::Super: + asImpl().writeDeclRef(NNS->getAsRecordDecl()); + continue; + } + llvm_unreachable("bad nested name specifier kind"); + } + } +}; + +} // end namespace serialization +} // end namespace clang + +#endif diff --git a/clang/include/clang/AST/AbstractTypeReader.h b/clang/include/clang/AST/AbstractTypeReader.h new file mode 100644 index 00000000000..9fea7b26f67 --- /dev/null +++ b/clang/include/clang/AST/AbstractTypeReader.h @@ -0,0 +1,31 @@ +//==--- AbstractTypeReader.h - Abstract deserialization for types ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_AST_ABSTRACTTYPEREADER_H +#define CLANG_AST_ABSTRACTTYPEREADER_H + +#include "clang/AST/Type.h" +#include "clang/AST/AbstractBasicReader.h" + +namespace clang { +namespace serialization { + +// template +// class AbstractTypeReader { +// public: +// AbstractTypeReader(PropertyReader &W); +// QualType read(Type::TypeClass kind); +// }; +// +// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp. +#include "clang/AST/AbstractTypeReader.inc" + +} // end namespace serialization +} // end namespace clang + +#endif diff --git a/clang/include/clang/AST/AbstractTypeWriter.h b/clang/include/clang/AST/AbstractTypeWriter.h new file mode 100644 index 00000000000..a63cb0be099 --- /dev/null +++ b/clang/include/clang/AST/AbstractTypeWriter.h @@ -0,0 +1,32 @@ +//==--- AbstractTypeWriter.h - Abstract serialization for types -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_AST_ABSTRACTTYPEWRITER_H +#define CLANG_AST_ABSTRACTTYPEWRITER_H + +#include "clang/AST/Type.h" +#include "clang/AST/AbstractBasicWriter.h" +#include "clang/AST/DeclObjC.h" + +namespace clang { +namespace serialization { + +// template +// class AbstractTypeWriter { +// public: +// AbstractTypeWriter(PropertyWriter &W); +// void write(QualType type); +// }; +// +// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp. +#include "clang/AST/AbstractTypeWriter.inc" + +} // end namespace serialization +} // end namespace clang + +#endif diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index d315dde6ed4..bbaa46363d9 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -32,83 +32,83 @@ #include namespace clang { - class ASTContext; - class AttributeCommonInfo; - class IdentifierInfo; - class ObjCInterfaceDecl; - class Expr; - class QualType; - class FunctionDecl; - class TypeSourceInfo; +class ASTContext; +class AttributeCommonInfo; +class IdentifierInfo; +class ObjCInterfaceDecl; +class Expr; +class QualType; +class FunctionDecl; +class TypeSourceInfo; /// Attr - This represents one attribute. - class Attr : public AttributeCommonInfo { - private: - unsigned AttrKind : 16; +class Attr : public AttributeCommonInfo { +private: + unsigned AttrKind : 16; - protected: - /// An index into the spelling list of an - /// attribute defined in Attr.td file. - unsigned Inherited : 1; - unsigned IsPackExpansion : 1; - unsigned Implicit : 1; - // FIXME: These are properties of the attribute kind, not state for this - // instance of the attribute. - unsigned IsLateParsed : 1; - unsigned InheritEvenIfAlreadyPresent : 1; +protected: + /// An index into the spelling list of an + /// attribute defined in Attr.td file. + unsigned Inherited : 1; + unsigned IsPackExpansion : 1; + unsigned Implicit : 1; + // FIXME: These are properties of the attribute kind, not state for this + // instance of the attribute. + unsigned IsLateParsed : 1; + unsigned InheritEvenIfAlreadyPresent : 1; - void *operator new(size_t bytes) noexcept { - llvm_unreachable("Attrs cannot be allocated with regular 'new'."); - } - void operator delete(void *data) noexcept { - llvm_unreachable("Attrs cannot be released with regular 'delete'."); - } + void *operator new(size_t bytes) noexcept { + llvm_unreachable("Attrs cannot be allocated with regular 'new'."); + } + void operator delete(void *data) noexcept { + llvm_unreachable("Attrs cannot be released with regular 'delete'."); + } - public: - // Forward so that the regular new and delete do not hide global ones. - void *operator new(size_t Bytes, ASTContext &C, - size_t Alignment = 8) noexcept { - return ::operator new(Bytes, C, Alignment); - } - void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { - return ::operator delete(Ptr, C, Alignment); - } +public: + // Forward so that the regular new and delete do not hide global ones. + void *operator new(size_t Bytes, ASTContext &C, + size_t Alignment = 8) noexcept { + return ::operator new(Bytes, C, Alignment); + } + void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { + return ::operator delete(Ptr, C, Alignment); + } - protected: - Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, - attr::Kind AK, bool IsLateParsed) - : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false), - IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed), - InheritEvenIfAlreadyPresent(false) {} +protected: + Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed) + : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false), + IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed), + InheritEvenIfAlreadyPresent(false) {} - public: - attr::Kind getKind() const { return static_cast(AttrKind); } +public: + attr::Kind getKind() const { return static_cast(AttrKind); } - unsigned getSpellingListIndex() const { - return getAttributeSpellingListIndex(); - } - const char *getSpelling() const; + unsigned getSpellingListIndex() const { + return getAttributeSpellingListIndex(); + } + const char *getSpelling() const; - SourceLocation getLocation() const { return getRange().getBegin(); } + SourceLocation getLocation() const { return getRange().getBegin(); } - bool isInherited() const { return Inherited; } + bool isInherited() const { return Inherited; } - /// Returns true if the attribute has been implicitly created instead - /// of explicitly written by the user. - bool isImplicit() const { return Implicit; } - void setImplicit(bool I) { Implicit = I; } + /// Returns true if the attribute has been implicitly created instead + /// of explicitly written by the user. + bool isImplicit() const { return Implicit; } + void setImplicit(bool I) { Implicit = I; } - void setPackExpansion(bool PE) { IsPackExpansion = PE; } - bool isPackExpansion() const { return IsPackExpansion; } + void setPackExpansion(bool PE) { IsPackExpansion = PE; } + bool isPackExpansion() const { return IsPackExpansion; } - // Clone this attribute. - Attr *clone(ASTContext &C) const; + // Clone this attribute. + Attr *clone(ASTContext &C) const; - bool isLateParsed() const { return IsLateParsed; } + bool isLateParsed() const { return IsLateParsed; } - // Pretty print this attribute. - void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; - }; + // Pretty print this attribute. + void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; +}; class TypeAttr : public Attr { protected: @@ -329,6 +329,18 @@ public: static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), "ParamIdx does not fit its serialization type"); +/// Contains information gathered from parsing the contents of TargetAttr. +struct ParsedTargetAttr { + std::vector Features; + StringRef Architecture; + StringRef BranchProtection; + bool DuplicateArchitecture = false; + bool operator ==(const ParsedTargetAttr &Other) const { + return DuplicateArchitecture == Other.DuplicateArchitecture && + Architecture == Other.Architecture && Features == Other.Features; + } +}; + #include "clang/AST/Attrs.inc" inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/clang/include/clang/AST/CXXInheritance.h b/clang/include/clang/AST/CXXInheritance.h index bb2ad9c64d3..f223c1f2f4f 100644 --- a/clang/include/clang/AST/CXXInheritance.h +++ b/clang/include/clang/AST/CXXInheritance.h @@ -372,6 +372,30 @@ class CXXFinalOverriderMap class CXXIndirectPrimaryBaseSet : public llvm::SmallSet {}; +inline bool +inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance) { + return Inheritance == MSInheritanceModel::Unspecified; +} + +// Only member pointers to functions need a this adjustment, since it can be +// combined with the field offset for data pointers. +inline bool inheritanceModelHasNVOffsetField(bool IsMemberFunction, + MSInheritanceModel Inheritance) { + return IsMemberFunction && Inheritance >= MSInheritanceModel::Multiple; +} + +inline bool +inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance) { + return Inheritance >= MSInheritanceModel::Virtual; +} + +inline bool inheritanceModelHasOnlyOneField(bool IsMemberFunction, + MSInheritanceModel Inheritance) { + if (IsMemberFunction) + return Inheritance <= MSInheritanceModel::Single; + return Inheritance <= MSInheritanceModel::Multiple; +} + } // namespace clang #endif // LLVM_CLANG_AST_CXXINHERITANCE_H diff --git a/clang/include/clang/AST/Comment.h b/clang/include/clang/AST/Comment.h index 2c284a271bb..cd9c1ce2bce 100644 --- a/clang/include/clang/AST/Comment.h +++ b/clang/include/clang/AST/Comment.h @@ -94,10 +94,11 @@ protected: unsigned : NumInlineContentCommentBits; - unsigned RenderKind : 2; + unsigned RenderKind : 3; + unsigned CommandID : CommandInfo::NumCommandIDBits; }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 3 + CommandInfo::NumCommandIDBits }; class HTMLTagCommentBitfields { @@ -310,7 +311,8 @@ public: RenderNormal, RenderBold, RenderMonospaced, - RenderEmphasized + RenderEmphasized, + RenderAnchor }; protected: diff --git a/clang/include/clang/AST/CommentCommands.td b/clang/include/clang/AST/CommentCommands.td index 3b0d1603d40..d387df7ce57 100644 --- a/clang/include/clang/AST/CommentCommands.td +++ b/clang/include/clang/AST/CommentCommands.td @@ -81,12 +81,13 @@ class RecordLikeDeclarationVerbatimLineCommand : // InlineCommand //===----------------------------------------------------------------------===// -def B : InlineCommand<"b">; -def C : InlineCommand<"c">; -def P : InlineCommand<"p">; -def A : InlineCommand<"a">; -def E : InlineCommand<"e">; -def Em : InlineCommand<"em">; +def B : InlineCommand<"b">; +def C : InlineCommand<"c">; +def P : InlineCommand<"p">; +def A : InlineCommand<"a">; +def E : InlineCommand<"e">; +def Em : InlineCommand<"em">; +def Anchor : InlineCommand<"anchor">; //===----------------------------------------------------------------------===// // BlockCommand diff --git a/clang/include/clang/AST/ComparisonCategories.h b/clang/include/clang/AST/ComparisonCategories.h index 9d591cc8149..70a78964b8a 100644 --- a/clang/include/clang/AST/ComparisonCategories.h +++ b/clang/include/clang/AST/ComparisonCategories.h @@ -41,23 +41,30 @@ class NamespaceDecl; /// partial_ordering, weak_ordering, and strong_ordering are collectively /// termed the comparison category types. enum class ComparisonCategoryType : unsigned char { - WeakEquality, - StrongEquality, PartialOrdering, WeakOrdering, StrongOrdering, - First = WeakEquality, + First = PartialOrdering, Last = StrongOrdering }; +/// Determine the common comparison type, as defined in C++2a +/// [class.spaceship]p4. +inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A, + ComparisonCategoryType B) { + return A < B ? A : B; +} + +/// Get the comparison category that should be used when comparing values of +/// type \c T. +Optional getComparisonCategoryForBuiltinCmp(QualType T); + /// An enumeration representing the possible results of a three-way /// comparison. These values map onto instances of comparison category types /// defined in the standard library. e.g. 'std::strong_ordering::less'. enum class ComparisonCategoryResult : unsigned char { Equal, Equivalent, - Nonequivalent, - Nonequal, Less, Greater, Unordered, @@ -125,21 +132,11 @@ public: return Info; } - /// True iff the comparison category is an equality comparison. - bool isEquality() const { return !isOrdered(); } - - /// True iff the comparison category is a relational comparison. - bool isOrdered() const { - using CCK = ComparisonCategoryType; - return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering || - Kind == CCK::StrongOrdering; - } - /// True iff the comparison is "strong". i.e. it checks equality and /// not equivalence. bool isStrong() const { using CCK = ComparisonCategoryType; - return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering; + return Kind == CCK::StrongOrdering; } /// True iff the comparison is not totally ordered. @@ -153,28 +150,18 @@ public: /// weak equivalence if needed. ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const { using CCR = ComparisonCategoryResult; - if (!isStrong()) { - if (Res == CCR::Equal) - return CCR::Equivalent; - if (Res == CCR::Nonequal) - return CCR::Nonequivalent; - } + if (!isStrong() && Res == CCR::Equal) + return CCR::Equivalent; return Res; } const ValueInfo *getEqualOrEquiv() const { return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal)); } - const ValueInfo *getNonequalOrNonequiv() const { - assert(isEquality()); - return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal)); - } const ValueInfo *getLess() const { - assert(isOrdered()); return getValueInfo(ComparisonCategoryResult::Less); } const ValueInfo *getGreater() const { - assert(isOrdered()); return getValueInfo(ComparisonCategoryResult::Greater); } const ValueInfo *getUnordered() const { @@ -221,7 +208,6 @@ public: return const_cast(This.lookupInfo(Kind)); } -private: const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const; private: diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index ce674e09c44..43c6c7b85db 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -15,6 +15,7 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContextAllocate.h" +#include "clang/AST/DeclAccessPair.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" @@ -59,6 +60,7 @@ class EnumDecl; class Expr; class FunctionTemplateDecl; class FunctionTemplateSpecializationInfo; +class FunctionTypeLoc; class LabelStmt; class MemberSpecializationInfo; class Module; @@ -76,33 +78,6 @@ class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; -/// A container of type source information. -/// -/// A client can read the relevant info using TypeLoc wrappers, e.g: -/// @code -/// TypeLoc TL = TypeSourceInfo->getTypeLoc(); -/// TL.getBeginLoc().print(OS, SrcMgr); -/// @endcode -class alignas(8) TypeSourceInfo { - // Contains a memory block after the class, used for type source information, - // allocated by ASTContext. - friend class ASTContext; - - QualType Ty; - - TypeSourceInfo(QualType ty) : Ty(ty) {} - -public: - /// Return the type wrapped by this type source info. - QualType getType() const { return Ty; } - - /// Return the TypeLoc wrapper for the type source info. - TypeLoc getTypeLoc() const; // implemented in TypeLoc.h - - /// Override the type stored in this TypeSourceInfo. Use with caution! - void overrideType(QualType T) { Ty = T; } -}; - /// The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; @@ -694,10 +669,12 @@ struct QualifierInfo { /// Represents a ValueDecl that came out of a declarator. /// Contains type source information through TypeSourceInfo. class DeclaratorDecl : public ValueDecl { - // A struct representing both a TInfo and a syntactic qualifier, - // to be used for the (uncommon) case of out-of-line declarations. + // A struct representing a TInfo, a trailing requires-clause and a syntactic + // qualifier, to be used for the (uncommon) case of out-of-line declarations + // and constrained function decls. struct ExtInfo : public QualifierInfo { TypeSourceInfo *TInfo; + Expr *TrailingRequiresClause = nullptr; }; llvm::PointerUnion DeclInfo; @@ -764,6 +741,21 @@ public: void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); + /// \brief Get the constraint-expression introduced by the trailing + /// requires-clause in the function/member declaration, or null if no + /// requires-clause was provided. + Expr *getTrailingRequiresClause() { + return hasExtInfo() ? getExtInfo()->TrailingRequiresClause + : nullptr; + } + + const Expr *getTrailingRequiresClause() const { + return hasExtInfo() ? getExtInfo()->TrailingRequiresClause + : nullptr; + } + + void setTrailingRequiresClause(Expr *TrailingRequiresClause); + unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; } @@ -777,6 +769,7 @@ public: ArrayRef TPLists); SourceLocation getTypeSpecStartLoc() const; + SourceLocation getTypeSpecEndLoc() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -898,6 +891,8 @@ protected: DAK_Normal }; + enum { NumScopeDepthOrObjCQualsBits = 7 }; + class ParmVarDeclBitfields { friend class ASTDeclReader; friend class ParmVarDecl; @@ -924,7 +919,7 @@ protected: /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was /// declared. - unsigned ScopeDepthOrObjCQuals : 7; + unsigned ScopeDepthOrObjCQuals : NumScopeDepthOrObjCQualsBits; /// The number of parameters preceding this parameter in the /// function parameter scope in which it was declared. @@ -1524,8 +1519,8 @@ public: /// need not have a usable destructor at all. bool isNoDestroy(const ASTContext &) const; - /// Do we need to emit an exit-time destructor for this variable, and if so, - /// what kind? + /// Would the destruction of this variable have any effect, and if so, what + /// kind? QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const; // Implement isa/cast/dyncast/etc. @@ -1649,6 +1644,10 @@ public: return ParmVarDeclBits.ScopeDepthOrObjCQuals; } + static constexpr unsigned getMaxFunctionScopeDepth() { + return (1u << NumScopeDepthOrObjCQualsBits) - 1; + } + /// Returns the index of this parameter in its prototype or method scope. unsigned getFunctionScopeIndex() const { return getParameterIndex(); @@ -1805,13 +1804,37 @@ public: TK_DependentFunctionTemplateSpecialization }; + /// Stashed information about a defaulted function definition whose body has + /// not yet been lazily generated. + class DefaultedFunctionInfo final + : llvm::TrailingObjects { + friend TrailingObjects; + unsigned NumLookups; + + public: + static DefaultedFunctionInfo *Create(ASTContext &Context, + ArrayRef Lookups); + /// Get the unqualified lookup results that should be used in this + /// defaulted function definition. + ArrayRef getUnqualifiedLookups() const { + return {getTrailingObjects(), NumLookups}; + } + }; + private: /// A new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo = nullptr; - LazyDeclStmtPtr Body; + /// The active member of this union is determined by + /// FunctionDeclBits.HasDefaultedFunctionInfo. + union { + /// The body of the function. + LazyDeclStmtPtr Body; + /// Information about a future defaulted function definition. + DefaultedFunctionInfo *DefaultedInfo; + }; unsigned ODRHash; @@ -1836,10 +1859,10 @@ private: /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion4 + llvm::PointerUnion TemplateOrSpecialization; /// Provides source/type location info for the declaration name embedded in @@ -1897,7 +1920,8 @@ protected: FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified, - ConstexprSpecKind ConstexprKind); + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr); using redeclarable_base = Redeclarable; @@ -1932,11 +1956,12 @@ public: SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified = false, bool hasWrittenPrototype = true, - ConstexprSpecKind ConstexprKind = CSK_unspecified) { + ConstexprSpecKind ConstexprKind = CSK_unspecified, + Expr *TrailingRequiresClause = nullptr) { DeclarationNameInfo NameInfo(N, NLoc); return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, SC, isInlineSpecified, hasWrittenPrototype, - ConstexprKind); + ConstexprKind, TrailingRequiresClause); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, @@ -1944,7 +1969,8 @@ public: const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified, bool hasWrittenPrototype, - ConstexprSpecKind ConstexprKind); + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause); static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1957,6 +1983,14 @@ public: void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } + /// Returns the location of the ellipsis of a variadic function. + SourceLocation getEllipsisLoc() const { + const auto *FPT = getType()->getAs(); + if (FPT && FPT->isVariadic()) + return FPT->getEllipsisLoc(); + return SourceLocation(); + } + SourceRange getSourceRange() const override LLVM_READONLY; // Function definitions. @@ -2030,18 +2064,30 @@ public: /// /// This does not determine whether the function has been defined (e.g., in a /// previous definition); for that information, use isDefined. + /// + /// Note: the function declaration does not become a definition until the + /// parser reaches the definition, if called before, this function will return + /// `false`. bool isThisDeclarationADefinition() const { - return isDeletedAsWritten() || isDefaulted() || Body || hasSkippedBody() || - isLateTemplateParsed() || willHaveBody() || hasDefiningAttr(); + return isDeletedAsWritten() || isDefaulted() || + doesThisDeclarationHaveABody() || hasSkippedBody() || + willHaveBody() || hasDefiningAttr(); } /// Returns whether this specific declaration of the function has a body. bool doesThisDeclarationHaveABody() const { - return Body || isLateTemplateParsed(); + return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) || + isLateTemplateParsed(); } void setBody(Stmt *B); - void setLazyBody(uint64_t Offset) { Body = Offset; } + void setLazyBody(uint64_t Offset) { + FunctionDeclBits.HasDefaultedFunctionInfo = false; + Body = LazyDeclStmtPtr(Offset); + } + + void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info); + DefaultedFunctionInfo *getDefaultedFunctionInfo() const; /// Whether this function is variadic. bool isVariadic() const; @@ -2096,6 +2142,16 @@ public: FunctionDeclBits.IsExplicitlyDefaulted = ED; } + /// True if this method is user-declared and was not + /// deleted or defaulted on its first declaration. + bool isUserProvided() const { + auto *DeclAsWritten = this; + if (FunctionDecl *Pattern = getTemplateInstantiationPattern()) + DeclAsWritten = Pattern; + return !(DeclAsWritten->isDeleted() || + DeclAsWritten->getCanonicalDecl()->isDefaulted()); + } + /// Whether falling off this function implicitly returns null/zero. /// If a more specific implicit return value is required, front-ends /// should synthesize the appropriate return statements. @@ -2177,6 +2233,10 @@ public: bool usesSEHTry() const { return FunctionDeclBits.UsesSEHTry; } void setUsesSEHTry(bool UST) { FunctionDeclBits.UsesSEHTry = UST; } + /// Indicates the function uses Floating Point constrained intrinsics + bool usesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; } + void setUsesFPIntrin(bool Val) { FunctionDeclBits.UsesFPIntrin = Val; } + /// Whether this function has been deleted. /// /// A function that is "deleted" (via the C++0x "= delete" syntax) @@ -2249,6 +2309,9 @@ public: /// true through IsAligned. bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; + /// Determine if this function provides an inline implementation of a builtin. + bool isInlineBuiltinDeclaration() const; + /// Determine whether this is a destroying operator delete. bool isDestroyingOperatorDelete() const; @@ -2312,6 +2375,17 @@ public: /// the target functionality. bool isTargetMultiVersion() const; + /// \brief Get the associated-constraints of this function declaration. + /// Currently, this will either be a vector of size 1 containing the + /// trailing-requires-clause or an empty vector. + /// + /// Use this instead of getTrailingRequiresClause for concepts APIs that + /// accept an ArrayRef of constraint expressions. + void getAssociatedConstraints(SmallVectorImpl &AC) const { + if (auto *TRC = getTrailingRequiresClause()) + AC.push_back(TRC); + } + void setPreviousDeclaration(FunctionDecl * PrevDecl); FunctionDecl *getCanonicalDecl() override; @@ -2362,6 +2436,12 @@ public: /// parameters have default arguments (in C++). unsigned getMinRequiredArguments() const; + /// Find the source location information for how the type of this function + /// was written. May be absent (for example if the function was declared via + /// a typedef) and may contain a different type from that of the function + /// (for example if the function type was adjusted by an attribute). + FunctionTypeLoc getFunctionTypeLoc() const; + QualType getReturnType() const { return getType()->castAs()->getReturnType(); } @@ -2371,6 +2451,12 @@ public: /// limited representation in the AST. SourceRange getReturnTypeSourceRange() const; + /// Attempt to compute an informative source range covering the + /// function parameters, including the ellipsis of a variadic function. + /// The source range excludes the parentheses, and is invalid if there are + /// no parameters and no ellipsis. + SourceRange getParametersSourceRange() const; + /// Get the declared return type, which may differ from the actual return /// type if the return type is deduced. QualType getDeclaredReturnType() const { diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 01c2f180977..91c372585b0 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1501,10 +1501,9 @@ class DeclContext { /// constructor or a destructor. uint64_t IsTrivialForCall : 1; - /// Used by CXXMethodDecl uint64_t IsDefaulted : 1; - /// Used by CXXMethodDecl uint64_t IsExplicitlyDefaulted : 1; + uint64_t HasDefaultedFunctionInfo : 1; uint64_t HasImplicitReturnZero : 1; uint64_t IsLateTemplateParsed : 1; @@ -1534,10 +1533,13 @@ class DeclContext { /// Store the ODRHash after first calculation. uint64_t HasODRHash : 1; + + /// Indicates if the function uses Floating Point Constrained Intrinsics + uint64_t UsesFPIntrin : 1; }; /// Number of non-inherited bits in FunctionDeclBitfields. - enum { NumFunctionDeclBits = 25 }; + enum { NumFunctionDeclBits = 27 }; /// Stores the bits used by CXXConstructorDecl. If modified /// NumCXXConstructorDeclBits and the accessor @@ -1554,7 +1556,7 @@ class DeclContext { /// exactly 64 bits and thus the width of NumCtorInitializers /// will need to be shrunk if some bit is added to NumDeclContextBitfields, /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields. - uint64_t NumCtorInitializers : 23; + uint64_t NumCtorInitializers : 21; uint64_t IsInheritingConstructor : 1; /// Whether this constructor has a trail-allocated explicit specifier. @@ -1590,6 +1592,9 @@ class DeclContext { /// True if this method is the getter or setter for an explicit property. uint64_t IsPropertyAccessor : 1; + /// True if this method is a synthesized property accessor stub. + uint64_t IsSynthesizedAccessorStub : 1; + /// Method has a definition. uint64_t IsDefined : 1; diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 66212f72b78..b716ea453a5 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -17,7 +17,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTUnresolvedSet.h" -#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" @@ -42,7 +41,6 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" @@ -1048,7 +1046,8 @@ public: /// Get all conversion functions visible in current class, /// including conversion function templates. - llvm::iterator_range getVisibleConversionFunctions(); + llvm::iterator_range + getVisibleConversionFunctions() const; /// Determine whether this class is an aggregate (C++ [dcl.init.aggr]), /// which is a class with no user-declared constructors, no private @@ -1737,10 +1736,10 @@ public: } /// Returns the inheritance model used for this record. - MSInheritanceAttr::Spelling getMSInheritanceModel() const; + MSInheritanceModel getMSInheritanceModel() const; /// Calculate what the inheritance model would be for this class. - MSInheritanceAttr::Spelling calculateInheritanceModel() const; + MSInheritanceModel calculateInheritanceModel() const; /// In the Microsoft C++ ABI, use zero for the field offset of a null data /// member pointer if we can guarantee that zero is not a valid field offset, @@ -1748,15 +1747,11 @@ public: /// vfptr at offset zero, so we can use zero for null. If there are multiple /// fields, we can use zero even if it is a valid field offset because /// null-ness testing will check the other fields. - bool nullFieldOffsetIsZero() const { - return !MSInheritanceAttr::hasOnlyOneField(/*IsMemberFunction=*/false, - getMSInheritanceModel()) || - (hasDefinition() && isPolymorphic()); - } + bool nullFieldOffsetIsZero() const; /// Controls when vtordisps will be emitted if this record is used as a /// virtual base. - MSVtorDispAttr::Mode getMSVtorDispMode() const; + MSVtorDispMode getMSVtorDispMode() const; /// Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be @@ -1788,7 +1783,7 @@ public: }; /// Store information needed for an explicit specifier. -/// used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl. +/// Used by CXXDeductionGuideDecl, CXXConstructorDecl and CXXConversionDecl. class ExplicitSpecifier { llvm::PointerIntPair ExplicitSpec{ nullptr, ExplicitSpecKind::ResolvedFalse}; @@ -1801,20 +1796,22 @@ public: const Expr *getExpr() const { return ExplicitSpec.getPointer(); } Expr *getExpr() { return ExplicitSpec.getPointer(); } - /// Return true if the ExplicitSpecifier isn't defaulted. + /// Determine if the declaration had an explicit specifier of any kind. bool isSpecified() const { return ExplicitSpec.getInt() != ExplicitSpecKind::ResolvedFalse || ExplicitSpec.getPointer(); } - /// Check for Equivalence of explicit specifiers. - /// Return True if the explicit specifier are equivalent false otherwise. + /// Check for equivalence of explicit specifiers. + /// \return true if the explicit specifier are equivalent, false otherwise. bool isEquivalent(const ExplicitSpecifier Other) const; - /// Return true if the explicit specifier is already resolved to be explicit. + /// Determine whether this specifier is known to correspond to an explicit + /// declaration. Returns false if the specifier is absent or has an + /// expression that is value-dependent or evaluates to false. bool isExplicit() const { return ExplicitSpec.getInt() == ExplicitSpecKind::ResolvedTrue; } - /// Return true if the ExplicitSpecifier isn't valid. + /// Determine if the explicit specifier is invalid. /// This state occurs after a substitution failures. bool isInvalid() const { return ExplicitSpec.getInt() == ExplicitSpecKind::Unresolved && @@ -1822,9 +1819,7 @@ public: } void setKind(ExplicitSpecKind Kind) { ExplicitSpec.setInt(Kind); } void setExpr(Expr *E) { ExplicitSpec.setPointer(E); } - // getFromDecl - retrieve the explicit specifier in the given declaration. - // if the given declaration has no explicit. the returned explicit specifier - // is defaulted. .isSpecified() will be false. + // Retrieve the explicit specifier in the given declaration, if any. static ExplicitSpecifier getFromDecl(FunctionDecl *Function); static const ExplicitSpecifier getFromDecl(const FunctionDecl *Function) { return getFromDecl(const_cast(Function)); @@ -1910,9 +1905,10 @@ protected: SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation) + SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr) : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo, SC, isInline, - ConstexprKind) { + ConstexprKind, TrailingRequiresClause) { if (EndLocation.isValid()) setRangeEnd(EndLocation); } @@ -1923,7 +1919,8 @@ public: const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInline, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation); + SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr); static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2001,16 +1998,6 @@ public: return const_cast(this)->getMostRecentDecl(); } - /// True if this method is user-declared and was not - /// deleted or defaulted on its first declaration. - bool isUserProvided() const { - auto *DeclAsWritten = this; - if (auto *Pattern = getTemplateInstantiationPattern()) - DeclAsWritten = cast(Pattern); - return !(DeclAsWritten->isDeleted() || - DeclAsWritten->getCanonicalDecl()->isDefaulted()); - } - void addOverriddenMethod(const CXXMethodDecl *MD); using method_iterator = const CXXMethodDecl *const *; @@ -2138,8 +2125,8 @@ class CXXCtorInitializer final { /// Either the base class name/delegating constructor type (stored as /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field /// (IndirectFieldDecl*) being initialized. - llvm::PointerUnion3 - Initializee; + llvm::PointerUnion + Initializee; /// The source location for the field name or, for a base initializer /// pack expansion, the location of the ellipsis. @@ -2378,7 +2365,8 @@ class CXXConstructorDecl final const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - InheritedConstructor Inherited); + InheritedConstructor Inherited, + Expr *TrailingRequiresClause); void anchor() override; @@ -2431,7 +2419,8 @@ public: const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, - InheritedConstructor Inherited = InheritedConstructor()); + InheritedConstructor Inherited = InheritedConstructor(), + Expr *TrailingRequiresClause = nullptr); ExplicitSpecifier getExplicitSpecifier() { return getCanonicalDecl()->getExplicitSpecifierInternal(); @@ -2638,9 +2627,11 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, - bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind) + bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, SourceLocation()) { + SC_None, isInline, ConstexprKind, SourceLocation(), + TrailingRequiresClause) { setImplicit(isImplicitlyDeclared); } @@ -2652,7 +2643,8 @@ public: const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared, - ConstexprSpecKind ConstexprKind); + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause = nullptr); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); @@ -2691,9 +2683,11 @@ class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, - ConstexprSpecKind ConstexprKind, SourceLocation EndLocation) + ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, + Expr *TrailingRequiresClause = nullptr) : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo, - SC_None, isInline, ConstexprKind, EndLocation), + SC_None, isInline, ConstexprKind, EndLocation, + TrailingRequiresClause), ExplicitSpec(ES) {} void anchor() override; @@ -2709,7 +2703,7 @@ public: Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, ExplicitSpecifier ES, ConstexprSpecKind ConstexprKind, - SourceLocation EndLocation); + SourceLocation EndLocation, Expr *TrailingRequiresClause = nullptr); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); ExplicitSpecifier getExplicitSpecifier() { @@ -2758,15 +2752,8 @@ public: /// Represents the language in a linkage specification. /// /// The values are part of the serialization ABI for - /// ASTs and cannot be changed without altering that ABI. To help - /// ensure a stable ABI for this, we choose the DW_LANG_ encodings - /// from the dwarf standard. - enum LanguageIDs { - lang_c = llvm::dwarf::DW_LANG_C, - lang_cxx = llvm::dwarf::DW_LANG_C_plus_plus, - lang_cxx_11 = llvm::dwarf::DW_LANG_C_plus_plus_11, - lang_cxx_14 = llvm::dwarf::DW_LANG_C_plus_plus_14 - }; + /// ASTs and cannot be changed without altering that ABI. + enum LanguageIDs { lang_c = 1, lang_cxx = 2 }; private: /// The source location for the extern keyword. @@ -3052,6 +3039,82 @@ public: static bool classofKind(Kind K) { return K == NamespaceAlias; } }; +/// Implicit declaration of a temporary that was materialized by +/// a MaterializeTemporaryExpr and lifetime-extended by a declaration +class LifetimeExtendedTemporaryDecl final + : public Decl, + public Mergeable { + friend class MaterializeTemporaryExpr; + friend class ASTDeclReader; + + Stmt *ExprWithTemporary = nullptr; + + /// The declaration which lifetime-extended this reference, if any. + /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. + ValueDecl *ExtendingDecl = nullptr; + unsigned ManglingNumber; + + mutable APValue *Value = nullptr; + + virtual void anchor(); + + LifetimeExtendedTemporaryDecl(Expr *Temp, ValueDecl *EDecl, unsigned Mangling) + : Decl(Decl::LifetimeExtendedTemporary, EDecl->getDeclContext(), + EDecl->getLocation()), + ExprWithTemporary(Temp), ExtendingDecl(EDecl), + ManglingNumber(Mangling) {} + + LifetimeExtendedTemporaryDecl(EmptyShell) + : Decl(Decl::LifetimeExtendedTemporary, EmptyShell{}) {} + +public: + static LifetimeExtendedTemporaryDecl *Create(Expr *Temp, ValueDecl *EDec, + unsigned Mangling) { + return new (EDec->getASTContext(), EDec->getDeclContext()) + LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling); + } + static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{}); + } + + ValueDecl *getExtendingDecl() { return ExtendingDecl; } + const ValueDecl *getExtendingDecl() const { return ExtendingDecl; } + + /// Retrieve the storage duration for the materialized temporary. + StorageDuration getStorageDuration() const; + + /// Retrieve the expression to which the temporary materialization conversion + /// was applied. This isn't necessarily the initializer of the temporary due + /// to the C++98 delayed materialization rules, but + /// skipRValueSubobjectAdjustments can be used to find said initializer within + /// the subexpression. + Expr *getTemporaryExpr() { return cast(ExprWithTemporary); } + const Expr *getTemporaryExpr() const { return cast(ExprWithTemporary); } + + unsigned getManglingNumber() const { return ManglingNumber; } + + /// Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getOrCreateValue(bool MayCreate) const; + + APValue *getValue() const { return Value; } + + // Iterators + Stmt::child_range childrenExpr() { + return Stmt::child_range(&ExprWithTemporary, &ExprWithTemporary + 1); + } + + Stmt::const_child_range childrenExpr() const { + return Stmt::const_child_range(&ExprWithTemporary, &ExprWithTemporary + 1); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == Decl::LifetimeExtendedTemporary; + } +}; + /// Represents a shadow declaration introduced into a scope by a /// (resolved) using declaration. /// diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 8d85ac36d86..b98aef6b499 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -172,6 +172,7 @@ private: Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, bool isPropertyAccessor = false, + bool isSynthesizedAccessorStub = false, bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, bool HasRelatedResultType = false); @@ -232,6 +233,7 @@ public: Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, bool isInstance = true, bool isVariadic = false, bool isPropertyAccessor = false, + bool isSynthesizedAccessorStub = false, bool isImplicitlyDeclared = false, bool isDefined = false, ImplementationControl impControl = None, bool HasRelatedResultType = false); @@ -408,7 +410,7 @@ public: /// \return the type for \c self and set \arg selfIsPseudoStrong and /// \arg selfIsConsumed accordingly. QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID, - bool &selfIsPseudoStrong, bool &selfIsConsumed); + bool &selfIsPseudoStrong, bool &selfIsConsumed) const; ImplicitParamDecl * getSelfDecl() const { return SelfDecl; } void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; } @@ -436,6 +438,14 @@ public: ObjCMethodDeclBits.IsPropertyAccessor = isAccessor; } + bool isSynthesizedAccessorStub() const { + return ObjCMethodDeclBits.IsSynthesizedAccessorStub; + } + + void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) { + ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub; + } + bool isDefined() const { return ObjCMethodDeclBits.IsDefined; } void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; } @@ -466,6 +476,9 @@ public: ObjCMethodDeclBits.HasSkippedBody = Skipped; } + /// True if the method is tagged as objc_direct + bool isDirectMethod() const; + /// Returns the property associated with this method's selector. /// /// Note that even if this particular method is not marked as a property @@ -747,13 +760,14 @@ public: /// property attribute rather than a type qualifier. OBJC_PR_nullability = 0x1000, OBJC_PR_null_resettable = 0x2000, - OBJC_PR_class = 0x4000 + OBJC_PR_class = 0x4000, + OBJC_PR_direct = 0x8000 // Adding a property should change NumPropertyAttrsBits }; enum { /// Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 15 + NumPropertyAttrsBits = 16 }; enum SetterKind { Assign, Retain, Copy, Weak }; @@ -876,6 +890,7 @@ public: bool isInstanceProperty() const { return !isClassProperty(); } bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } + bool isDirectProperty() const { return PropertyAttributes & OBJC_PR_direct; } ObjCPropertyQueryKind getQueryKind() const { return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class : @@ -2779,6 +2794,11 @@ private: /// Null for \@dynamic. Required for \@synthesize. ObjCIvarDecl *PropertyIvarDecl; + /// The getter's definition, which has an empty body if synthesized. + ObjCMethodDecl *GetterMethodDecl = nullptr; + /// The getter's definition, which has an empty body if synthesized. + ObjCMethodDecl *SetterMethodDecl = nullptr; + /// Null for \@dynamic. Non-null if property must be copy-constructed in /// getter. Expr *GetterCXXConstructor = nullptr; @@ -2845,6 +2865,12 @@ public: return IvarLoc.isValid() && IvarLoc != getLocation(); } + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } + void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; } + + ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } + void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; } + Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index ec14adc7de9..7a55d04a0f3 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_DECLTEMPLATE_H #define LLVM_CLANG_AST_DECLTEMPLATE_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -51,14 +52,15 @@ class NonTypeTemplateParmDecl; class TemplateDecl; class TemplateTemplateParmDecl; class TemplateTypeParmDecl; +class ConceptDecl; class UnresolvedSetImpl; class VarTemplateDecl; class VarTemplatePartialSpecializationDecl; /// Stores a template parameter of any kind. using TemplateParameter = - llvm::PointerUnion3; + llvm::PointerUnion; NamedDecl *getAsNamedDecl(TemplateParameter P); @@ -81,20 +83,24 @@ class TemplateParameterList final /// pack. unsigned ContainsUnexpandedParameterPack : 1; - /// Whether this template parameter list has an associated requires-clause + /// Whether this template parameter list has a requires clause. unsigned HasRequiresClause : 1; + /// Whether any of the template parameters has constrained-parameter + /// constraint-expression. + unsigned HasConstrainedParameters : 1; + protected: - TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ArrayRef Params, SourceLocation RAngleLoc, - Expr *RequiresClause); + TemplateParameterList(const ASTContext& C, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, ArrayRef Params, + SourceLocation RAngleLoc, Expr *RequiresClause); size_t numTrailingObjects(OverloadToken) const { return NumParams; } size_t numTrailingObjects(OverloadToken) const { - return HasRequiresClause; + return HasRequiresClause ? 1 : 0; } public: @@ -158,14 +164,22 @@ public: return ContainsUnexpandedParameterPack; } + /// Determine whether this template parameter list contains a parameter pack. + bool hasParameterPack() const { + for (const NamedDecl *P : asArray()) + if (P->isParameterPack()) + return true; + return false; + } + /// The constraint-expression of the associated requires-clause. Expr *getRequiresClause() { - return HasRequiresClause ? *getTrailingObjects() : nullptr; + return HasRequiresClause ? getTrailingObjects()[0] : nullptr; } /// The constraint-expression of the associated requires-clause. const Expr *getRequiresClause() const { - return HasRequiresClause ? *getTrailingObjects() : nullptr; + return HasRequiresClause ? getTrailingObjects()[0] : nullptr; } /// \brief All associated constraints derived from this template parameter @@ -208,15 +222,16 @@ class FixedSizeTemplateParameterListStorage >::type storage; public: - FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, + FixedSizeTemplateParameterListStorage(const ASTContext &C, + SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef Params, SourceLocation RAngleLoc, Expr *RequiresClause) : FixedSizeStorageOwner( (assert(N == Params.size()), - assert(HasRequiresClause == static_cast(RequiresClause)), - new (static_cast(&storage)) TemplateParameterList( + assert(HasRequiresClause == (RequiresClause != nullptr)), + new (static_cast(&storage)) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {} }; @@ -309,7 +324,7 @@ class DefaultArgStorage { static_assert(sizeof(Chain) == sizeof(void *) * 2, "non-pointer argument type?"); - llvm::PointerUnion3 ValueOrInherited; + llvm::PointerUnion ValueOrInherited; static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); @@ -793,9 +808,10 @@ protected: void loadLazySpecializationsImpl() const; - template typename SpecEntryTraits::DeclType* + template + typename SpecEntryTraits::DeclType* findSpecializationImpl(llvm::FoldingSetVector &Specs, - ArrayRef Args, void *&InsertPos); + void *&InsertPos, ProfileArguments &&...ProfileArgs); template void addSpecializationImpl(llvm::FoldingSetVector &Specs, @@ -1147,9 +1163,12 @@ public: /// \code /// template class vector; /// \endcode -class TemplateTypeParmDecl : public TypeDecl { +class TemplateTypeParmDecl final : public TypeDecl, + private llvm::TrailingObjects { /// Sema creates these on the stack during auto type deduction. friend class Sema; + friend TrailingObjects; + friend class ASTDeclReader; /// Whether this template type parameter was declaration with /// the 'typename' keyword. @@ -1157,6 +1176,22 @@ class TemplateTypeParmDecl : public TypeDecl { /// If false, it was declared with the 'class' keyword. bool Typename : 1; + /// Whether this template type parameter has a type-constraint construct. + bool HasTypeConstraint : 1; + + /// Whether the type constraint has been initialized. This can be false if the + /// constraint was not initialized yet or if there was an error forming the + /// type constriant. + bool TypeConstraintInitialized : 1; + + /// Whether this non-type template parameter is an "expanded" + /// parameter pack, meaning that its type is a pack expansion and we + /// already know the set of types that expansion expands to. + bool ExpandedParameterPack : 1; + + /// The number of type parameters in an expanded parameter pack. + unsigned NumExpanded = 0; + /// The default template argument, if any. using DefArgStorage = DefaultArgStorage; @@ -1164,8 +1199,12 @@ class TemplateTypeParmDecl : public TypeDecl { TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, - bool Typename) - : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename) {} + bool Typename, bool HasTypeConstraint, + Optional NumExpanded) + : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), + HasTypeConstraint(HasTypeConstraint), TypeConstraintInitialized(false), + ExpandedParameterPack(NumExpanded), + NumExpanded(NumExpanded ? *NumExpanded : 0) {} public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, @@ -1173,15 +1212,24 @@ public: SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, - bool ParameterPack); + bool ParameterPack, + bool HasTypeConstraint = false, + Optional NumExpanded = None); + static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, unsigned ID); + static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, + unsigned ID, + bool HasTypeConstraint); /// Whether this template type parameter was declared with /// the 'typename' keyword. /// - /// If not, it was declared with the 'class' keyword. - bool wasDeclaredWithTypename() const { return Typename; } + /// If not, it was either declared with the 'class' keyword or with a + /// type-constraint (see hasTypeConstraint()). + bool wasDeclaredWithTypename() const { + return Typename && !HasTypeConstraint; + } const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } @@ -1238,6 +1286,78 @@ public: /// Returns whether this is a parameter pack. bool isParameterPack() const; + /// Whether this parameter pack is a pack expansion. + /// + /// A template type template parameter pack can be a pack expansion if its + /// type-constraint contains an unexpanded parameter pack. + bool isPackExpansion() const { + if (!isParameterPack()) + return false; + if (const TypeConstraint *TC = getTypeConstraint()) + if (TC->hasExplicitTemplateArgs()) + for (const auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments()) + if (ArgLoc.getArgument().containsUnexpandedParameterPack()) + return true; + return false; + } + + /// Whether this parameter is a template type parameter pack that has a known + /// list of different type-constraints at different positions. + /// + /// A parameter pack is an expanded parameter pack when the original + /// parameter pack's type-constraint was itself a pack expansion, and that + /// expansion has already been expanded. For example, given: + /// + /// \code + /// template + /// struct X { + /// template ...Convertibles> + /// struct Y { /* ... */ }; + /// }; + /// \endcode + /// + /// The parameter pack \c Convertibles has (convertible_to && ...) as + /// its type-constraint. When \c Types is supplied with template arguments by + /// instantiating \c X, the instantiation of \c Convertibles becomes an + /// expanded parameter pack. For example, instantiating + /// \c X results in \c Convertibles being an expanded + /// parameter pack of size 2 (use getNumExpansionTypes() to get this number). + bool isExpandedParameterPack() const { return ExpandedParameterPack; } + + /// Retrieves the number of parameters in an expanded parameter pack. + unsigned getNumExpansionParameters() const { + assert(ExpandedParameterPack && "Not an expansion parameter pack"); + return NumExpanded; + } + + /// Returns the type constraint associated with this template parameter (if + /// any). + const TypeConstraint *getTypeConstraint() const { + return TypeConstraintInitialized ? getTrailingObjects() : + nullptr; + } + + void setTypeConstraint(NestedNameSpecifierLoc NNS, + DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, + ConceptDecl *CD, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + Expr *ImmediatelyDeclaredConstraint); + + /// Determine whether this template parameter has a type-constraint. + bool hasTypeConstraint() const { + return HasTypeConstraint; + } + + /// \brief Get the associated-constraints of this template parameter. + /// This will either be the immediately-introduced constraint or empty. + /// + /// Use this instead of getConstraintExpression for concepts APIs that + /// accept an ArrayRef of constraint expressions. + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + if (HasTypeConstraint) + AC.push_back(getTypeConstraint()->getImmediatelyDeclaredConstraint()); + } + SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. @@ -1423,6 +1543,33 @@ public: return TypesAndInfos[I].second; } + /// Return the type-constraint in the placeholder type of this non-type + /// template parameter (if any). + TypeConstraint *getPlaceholderTypeConstraint() const { + // TODO: Concepts: Implement once we have actual placeholders with type + // constraints. + return nullptr; + } + + /// Determine whether this non-type template parameter's type has a + /// placeholder with a type-constraint. + bool hasPlaceholderTypeConstraint() const { + // TODO: Concepts: Implement once we have actual placeholders with type + // constraints. + return false; + } + + /// \brief Get the associated-constraints of this template parameter. + /// This will either be a vector of size 1 containing the immediately-declared + /// constraint introduced by the placeholder type, or an empty vector. + /// + /// Use this instead of getPlaceholderImmediatelyDeclaredConstraint for + /// concepts APIs that accept an ArrayRef of constraint expressions. + void getAssociatedConstraints(llvm::SmallVectorImpl &AC) const { + if (TypeConstraint *TC = getPlaceholderTypeConstraint()) + AC.push_back(TC->getImmediatelyDeclaredConstraint()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } @@ -1557,8 +1704,8 @@ public: /// Retrieve the default argument, if any. const TemplateArgumentLoc &getDefaultArgument() const { - static const TemplateArgumentLoc None; - return DefaultArgument.isSet() ? *DefaultArgument.get() : None; + static const TemplateArgumentLoc NoneLoc; + return DefaultArgument.isSet() ? *DefaultArgument.get() : NoneLoc; } /// Retrieve the location of the default argument, if any. @@ -2056,7 +2203,14 @@ public: ->getInjectedSpecializationType(); } - // FIXME: Add Profile support! + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(), + getASTContext()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, + TemplateParameterList *TPL, ASTContext &Context); static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2180,7 +2334,8 @@ public: /// Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. ClassTemplatePartialSpecializationDecl * - findPartialSpecialization(ArrayRef Args, void *&InsertPos); + findPartialSpecialization(ArrayRef Args, + TemplateParameterList *TPL, void *&InsertPos); /// Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. @@ -2880,6 +3035,15 @@ public: return First->InstantiatedFromMember.setInt(true); } + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(), + getASTContext()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, + TemplateParameterList *TPL, ASTContext &Context); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { @@ -2998,7 +3162,8 @@ public: /// Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. VarTemplatePartialSpecializationDecl * - findPartialSpecialization(ArrayRef Args, void *&InsertPos); + findPartialSpecialization(ArrayRef Args, + TemplateParameterList *TPL, void *&InsertPos); /// Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. @@ -3067,6 +3232,10 @@ public: ConstraintExpr->getEndLoc()); } + bool isTypeConcept() const { + return isa(getTemplateParameters()->getParam(0)); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Concept; } diff --git a/clang/include/clang/AST/DeclarationName.h b/clang/include/clang/AST/DeclarationName.h index 90449147637..82f6868e3a7 100644 --- a/clang/include/clang/AST/DeclarationName.h +++ b/clang/include/clang/AST/DeclarationName.h @@ -528,7 +528,7 @@ public: static int compare(DeclarationName LHS, DeclarationName RHS); - void print(raw_ostream &OS, const PrintingPolicy &Policy); + void print(raw_ostream &OS, const PrintingPolicy &Policy) const; void dump() const; }; @@ -792,7 +792,7 @@ public: std::string getAsString() const; /// printName - Print the human-readable name to a stream. - void printName(raw_ostream &OS) const; + void printName(raw_ostream &OS, PrintingPolicy Policy) const; /// getBeginLoc - Retrieve the location of the first token. SourceLocation getBeginLoc() const { return NameLoc; } @@ -829,11 +829,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, return PD; } -inline raw_ostream &operator<<(raw_ostream &OS, - DeclarationNameInfo DNInfo) { - DNInfo.printName(OS); - return OS; -} +raw_ostream &operator<<(raw_ostream &OS, DeclarationNameInfo DNInfo); } // namespace clang diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index ffa7d4db96a..16956c27a11 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -494,7 +494,13 @@ public: /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in /// C. - bool isKnownToHaveBooleanValue() const; + /// + /// \param Semantic If true, only return true for expressions that are known + /// to be semantically boolean, which might not be true even for expressions + /// that are known to evaluate to 0/1. For instance, reading an unsigned + /// bit-field with width '1' will evaluate to 0/1, but doesn't necessarily + /// semantically correspond to a bool. + bool isKnownToHaveBooleanValue(bool Semantic = true) const; /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a @@ -756,6 +762,15 @@ public: /// member expression. static QualType findBoundMemberType(const Expr *expr); + /// Skip past any invisble AST nodes which might surround this + /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes, + /// but also injected CXXMemberExpr and CXXConstructExpr which represent + /// implicit conversions. + Expr *IgnoreUnlessSpelledInSource(); + const Expr *IgnoreUnlessSpelledInSource() const { + return const_cast(this)->IgnoreUnlessSpelledInSource(); + } + /// Skip past any implicit casts which might surround this expression until /// reaching a fixed point. Skips: /// * ImplicitCastExpr @@ -786,6 +801,16 @@ public: return const_cast(this)->IgnoreImplicit(); } + /// Skip past any implicit AST nodes which might surround this expression + /// until reaching a fixed point. Same as IgnoreImplicit, except that it + /// also skips over implicit calls to constructors and conversion functions. + /// + /// FIXME: Should IgnoreImplicit do this? + Expr *IgnoreImplicitAsWritten() LLVM_READONLY; + const Expr *IgnoreImplicitAsWritten() const { + return const_cast(this)->IgnoreImplicitAsWritten(); + } + /// Skip past any parentheses which might surround this expression until /// reaching a fixed point. Skips: /// * ParenExpr @@ -3711,22 +3736,25 @@ class ConditionalOperator : public AbstractConditionalOperator { friend class ASTStmtReader; public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - SourceLocation CLoc, Expr *rhs, - QualType t, ExprValueKind VK, ExprObjectKind OK) - : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, - // FIXME: the type of the conditional operator doesn't - // depend on the type of the conditional, but the standard - // seems to imply that it could. File a bug! - (lhs->isTypeDependent() || rhs->isTypeDependent()), - (cond->isValueDependent() || lhs->isValueDependent() || - rhs->isValueDependent()), - (cond->isInstantiationDependent() || - lhs->isInstantiationDependent() || - rhs->isInstantiationDependent()), - (cond->containsUnexpandedParameterPack() || - lhs->containsUnexpandedParameterPack() || - rhs->containsUnexpandedParameterPack()), - QLoc, CLoc) { + SourceLocation CLoc, Expr *rhs, QualType t, + ExprValueKind VK, ExprObjectKind OK) + : AbstractConditionalOperator( + ConditionalOperatorClass, t, VK, OK, + // The type of the conditional operator depends on the type + // of the conditional to support the GCC vector conditional + // extension. Additionally, [temp.dep.expr] does specify state that + // this should be dependent on ALL sub expressions. + (cond->isTypeDependent() || lhs->isTypeDependent() || + rhs->isTypeDependent()), + (cond->isValueDependent() || lhs->isValueDependent() || + rhs->isValueDependent()), + (cond->isInstantiationDependent() || + lhs->isInstantiationDependent() || + rhs->isInstantiationDependent()), + (cond->containsUnexpandedParameterPack() || + lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack()), + QLoc, CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -5594,6 +5622,20 @@ public: } }; +/// Copy initialization expr of a __block variable and a boolean flag that +/// indicates whether the expression can throw. +struct BlockVarCopyInit { + BlockVarCopyInit() = default; + BlockVarCopyInit(Expr *CopyExpr, bool CanThrow) + : ExprAndFlag(CopyExpr, CanThrow) {} + void setExprAndFlag(Expr *CopyExpr, bool CanThrow) { + ExprAndFlag.setPointerAndInt(CopyExpr, CanThrow); + } + Expr *getCopyExpr() const { return ExprAndFlag.getPointer(); } + bool canThrow() const { return ExprAndFlag.getInt(); } + llvm::PointerIntPair ExprAndFlag; +}; + /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] /// This AST node provides support for reinterpreting a type to another /// type of the same size. diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 2152e108c7c..2c29409e0ca 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_EXPRCXX_H #define LLVM_CLANG_AST_EXPRCXX_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -4421,70 +4422,66 @@ private: friend class ASTStmtReader; friend class ASTStmtWriter; - struct ExtraState { - /// The temporary-generating expression whose value will be - /// materialized. - Stmt *Temporary; - - /// The declaration which lifetime-extended this reference, if any. - /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. - const ValueDecl *ExtendingDecl; - - unsigned ManglingNumber; - }; - llvm::PointerUnion State; + llvm::PointerUnion State; public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference) - : Expr(MaterializeTemporaryExprClass, T, - BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, - Temporary->isTypeDependent(), Temporary->isValueDependent(), - Temporary->isInstantiationDependent(), - Temporary->containsUnexpandedParameterPack()), - State(Temporary) {} + bool BoundToLvalueReference, + LifetimeExtendedTemporaryDecl *MTD = nullptr); MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) {} - Stmt *getTemporary() const { - return State.is() ? State.get() - : State.get()->Temporary; - } - /// Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast(getTemporary()); } + Expr *getSubExpr() const { + return cast( + State.is() + ? State.get() + : State.get()->getTemporaryExpr()); + } /// Retrieve the storage duration for the materialized temporary. StorageDuration getStorageDuration() const { - const ValueDecl *ExtendingDecl = getExtendingDecl(); - if (!ExtendingDecl) - return SD_FullExpression; - // FIXME: This is not necessarily correct for a temporary materialized - // within a default initializer. - if (isa(ExtendingDecl)) - return SD_Automatic; - // FIXME: This only works because storage class specifiers are not allowed - // on decomposition declarations. - if (isa(ExtendingDecl)) - return ExtendingDecl->getDeclContext()->isFunctionOrMethod() - ? SD_Automatic - : SD_Static; - return cast(ExtendingDecl)->getStorageDuration(); + return State.is() ? SD_FullExpression + : State.get() + ->getStorageDuration(); + } + + /// Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getOrCreateValue(bool MayCreate) const { + assert(State.is() && + "the temporary has not been lifetime extended"); + return State.get()->getOrCreateValue( + MayCreate); + } + + LifetimeExtendedTemporaryDecl *getLifetimeExtendedTemporaryDecl() { + return State.dyn_cast(); + } + const LifetimeExtendedTemporaryDecl * + getLifetimeExtendedTemporaryDecl() const { + return State.dyn_cast(); } /// Get the declaration which triggered the lifetime-extension of this /// temporary, if any. - const ValueDecl *getExtendingDecl() const { + ValueDecl *getExtendingDecl() { return State.is() ? nullptr - : State.get()->ExtendingDecl; + : State.get() + ->getExtendingDecl(); + } + const ValueDecl *getExtendingDecl() const { + return const_cast(this)->getExtendingDecl(); } - void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); + void setExtendingDecl(ValueDecl *ExtendedBy, unsigned ManglingNumber); unsigned getManglingNumber() const { - return State.is() ? 0 : State.get()->ManglingNumber; + return State.is() ? 0 + : State.get() + ->getManglingNumber(); } /// Determine whether this materialized temporary is bound to an @@ -4494,11 +4491,11 @@ public: } SourceLocation getBeginLoc() const LLVM_READONLY { - return getTemporary()->getBeginLoc(); + return getSubExpr()->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { - return getTemporary()->getEndLoc(); + return getSubExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -4507,20 +4504,18 @@ public: // Iterators child_range children() { - if (State.is()) - return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1); - - auto ES = State.get(); - return child_range(&ES->Temporary, &ES->Temporary + 1); + return State.is() + ? child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1) + : State.get()->childrenExpr(); } const_child_range children() const { - if (State.is()) - return const_child_range(State.getAddrOfPtr1(), - State.getAddrOfPtr1() + 1); - - auto ES = State.get(); - return const_child_range(&ES->Temporary, &ES->Temporary + 1); + return State.is() + ? const_child_range(State.getAddrOfPtr1(), + State.getAddrOfPtr1() + 1) + : const_cast( + State.get()) + ->childrenExpr(); } }; @@ -4846,107 +4841,81 @@ public: /// /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the /// specialization of a concept results in a prvalue of type bool. -class ConceptSpecializationExpr final : public Expr, +class ConceptSpecializationExpr final : public Expr, public ConceptReference, private llvm::TrailingObjects { friend class ASTStmtReader; friend TrailingObjects; +public: + using SubstitutionDiagnostic = std::pair; - // \brief The optional nested name specifier used when naming the concept. - NestedNameSpecifierLoc NestedNameSpec; - - /// \brief The location of the template keyword, if specified when naming the - /// concept. - SourceLocation TemplateKWLoc; - - /// \brief The location of the concept name in the expression. - SourceLocation ConceptNameLoc; - - /// \brief The declaration found by name lookup when the expression was - /// created. - /// Can differ from NamedConcept when, for example, the concept was found - /// through a UsingShadowDecl. - NamedDecl *FoundDecl; - - /// \brief The concept named, and whether or not the concept with the given - /// arguments was satisfied when the expression was created. - /// If any of the template arguments are dependent (this expr would then be - /// isValueDependent()), this bit is to be ignored. - llvm::PointerIntPair NamedConcept; - - /// \brief The template argument list source info used to specialize the - /// concept. - const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - +protected: /// \brief The number of template arguments in the tail-allocated list of /// converted template arguments. unsigned NumTemplateArgs; - ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS, + /// \brief Information about the satisfaction of the named concept with the + /// given arguments. If this expression is value dependent, this is to be + /// ignored. + ASTConstraintSatisfaction *Satisfaction; + + ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - SourceLocation ConceptNameLoc, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, + DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, ArrayRef ConvertedArgs, - Optional IsSatisfied); + const ConstraintSatisfaction *Satisfaction); ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); public: static ConceptSpecializationExpr * - Create(ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc, + Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef ConvertedArgs, Optional IsSatisfied); + ArrayRef ConvertedArgs, + const ConstraintSatisfaction *Satisfaction); static ConceptSpecializationExpr * Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); - const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { - return NestedNameSpec; - } - - NamedDecl *getFoundDecl() const { - return FoundDecl; - } - - ConceptDecl *getNamedConcept() const { - return NamedConcept.getPointer(); - } - ArrayRef getTemplateArguments() const { return ArrayRef(getTrailingObjects(), NumTemplateArgs); } - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return ArgsAsWritten; - } - /// \brief Set new template arguments for this concept specialization. - void setTemplateArguments(const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef Converted); + void setTemplateArguments(ArrayRef Converted); /// \brief Whether or not the concept with the given arguments was satisfied - /// when the expression was created. This method assumes that the expression - /// is not dependent! + /// when the expression was created. + /// The expression must not be dependent. bool isSatisfied() const { assert(!isValueDependent() && "isSatisfied called on a dependent ConceptSpecializationExpr"); - return NamedConcept.getInt(); + return Satisfaction->IsSatisfied; } - SourceLocation getConceptNameLoc() const { return ConceptNameLoc; } - - SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; } + /// \brief Get elaborated satisfaction info about the template arguments' + /// satisfaction of the named concept. + /// The expression must not be dependent. + const ASTConstraintSatisfaction &getSatisfaction() const { + assert(!isValueDependent() + && "getSatisfaction called on dependent ConceptSpecializationExpr"); + return *Satisfaction; + } static bool classof(const Stmt *T) { return T->getStmtClass() == ConceptSpecializationExprClass; } - SourceLocation getBeginLoc() const LLVM_READONLY { return ConceptNameLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { + return ConceptName.getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY { return ArgsAsWritten->RAngleLoc; } diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index dbb2b2ff709..d76b3a26b1f 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -642,7 +642,7 @@ private: /// the location of the 'super' keyword. When it's an interface, /// this is that interface. SourceLocation ReceiverLoc; - llvm::PointerUnion3 Receiver; + llvm::PointerUnion Receiver; public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 304633668bd..899ac3f6693 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -66,9 +66,8 @@ class ExternalASTSource : public RefCountedBase { /// whenever we might have added new redeclarations for existing decls. uint32_t CurrentGeneration = 0; - /// Whether this AST source also provides information for - /// semantic analysis. - bool SemaSource = false; + /// LLVM-style RTTI. + static char ID; public: ExternalASTSource() = default; @@ -325,6 +324,12 @@ public: virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + /// LLVM-style RTTI. + /// \{ + virtual bool isA(const void *ClassID) const { return ClassID == &ID; } + static bool classof(const ExternalASTSource *S) { return S->isA(&ID); } + /// \} + protected: static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 5f34440b8b5..4023e023e9d 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -16,12 +16,13 @@ #define LLVM_CLANG_AST_JSONNODEDUMPER_H #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTNodeTraverser.h" #include "clang/AST/ASTDumperUtils.h" +#include "clang/AST/ASTNodeTraverser.h" #include "clang/AST/AttrVisitor.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/Mangle.h" #include "llvm/Support/JSON.h" namespace clang { @@ -122,9 +123,10 @@ class JSONNodeDumper const SourceManager &SM; ASTContext& Ctx; + ASTNameGenerator ASTNameGen; PrintingPolicy PrintPolicy; const comments::CommandTraits *Traits; - StringRef LastLocFilename; + StringRef LastLocFilename, LastLocPresumedFilename; unsigned LastLocLine, LastLocPresumedLine; using InnerAttrVisitor = ConstAttrVisitor; @@ -182,8 +184,9 @@ public: JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, const PrintingPolicy &PrintPolicy, const comments::CommandTraits *Traits) - : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), PrintPolicy(PrintPolicy), - Traits(Traits), LastLocLine(0), LastLocPresumedLine(0) {} + : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx), + PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0), + LastLocPresumedLine(0) {} void Visit(const Attr *A); void Visit(const Stmt *Node); diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index b2a2035dcb3..26f8389f9cf 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -30,6 +30,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" @@ -111,7 +112,7 @@ class OMPClauseWithPreInit { Stmt *PreInit = nullptr; /// Region that captures the associated stmt. - OpenMPDirectiveKind CaptureRegion = OMPD_unknown; + OpenMPDirectiveKind CaptureRegion = llvm::omp::OMPD_unknown; protected: OMPClauseWithPreInit(const OMPClause *This) { @@ -119,7 +120,9 @@ protected: } /// Set pre-initialization statement for the clause. - void setPreInitStmt(Stmt *S, OpenMPDirectiveKind ThisRegion = OMPD_unknown) { + void + setPreInitStmt(Stmt *S, + OpenMPDirectiveKind ThisRegion = llvm::omp::OMPD_unknown) { PreInit = S; CaptureRegion = ThisRegion; } @@ -432,7 +435,7 @@ class OMPIfClause : public OMPClause, public OMPClauseWithPreInit { SourceLocation ColonLoc; /// Directive name modifier for the clause. - OpenMPDirectiveKind NameModifier = OMPD_unknown; + OpenMPDirectiveKind NameModifier = llvm::omp::OMPD_unknown; /// Name modifier location. SourceLocation NameModifierLoc; @@ -943,7 +946,7 @@ class OMPProcBindClause : public OMPClause { SourceLocation LParenLoc; /// A kind of the 'proc_bind' clause. - OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown; + llvm::omp::ProcBindKind Kind = llvm::omp::OMP_PROC_BIND_unknown; /// Start location of the kind in source code. SourceLocation KindKwLoc; @@ -951,7 +954,7 @@ class OMPProcBindClause : public OMPClause { /// Set kind of the clause. /// /// \param K Kind of clause. - void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; } + void setProcBindKind(llvm::omp::ProcBindKind K) { Kind = K; } /// Set clause kind location. /// @@ -967,7 +970,7 @@ public: /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc, + OMPProcBindClause(llvm::omp::ProcBindKind A, SourceLocation ALoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), @@ -984,7 +987,7 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } /// Returns kind of the clause. - OpenMPProcBindClauseKind getProcBindKind() const { return Kind; } + llvm::omp::ProcBindKind getProcBindKind() const { return Kind; } /// Returns location of clause kind. SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; } @@ -2150,6 +2153,13 @@ class OMPLastprivateClause final friend OMPVarListClause; friend TrailingObjects; + /// Optional lastprivate kind, e.g. 'conditional', if specified by user. + OpenMPLastprivateModifier LPKind; + /// Optional location of the lasptrivate kind, if specified by user. + SourceLocation LPKindLoc; + /// Optional colon location, if specified by user. + SourceLocation ColonLoc; + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -2157,10 +2167,13 @@ class OMPLastprivateClause final /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) + SourceLocation EndLoc, OpenMPLastprivateModifier LPKind, + SourceLocation LPKindLoc, SourceLocation ColonLoc, + unsigned N) : OMPVarListClause(OMPC_lastprivate, StartLoc, LParenLoc, EndLoc, N), - OMPClauseWithPostUpdate(this) {} + OMPClauseWithPostUpdate(this), LPKind(LPKind), LPKindLoc(LPKindLoc), + ColonLoc(ColonLoc) {} /// Build an empty clause. /// @@ -2221,6 +2234,13 @@ class OMPLastprivateClause final return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size()); } + /// Sets lastprivate kind. + void setKind(OpenMPLastprivateModifier Kind) { LPKind = Kind; } + /// Sets location of the lastprivate kind. + void setKindLoc(SourceLocation Loc) { LPKindLoc = Loc; } + /// Sets colon symbol location. + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + public: /// Creates clause with a list of variables \a VL. /// @@ -2242,6 +2262,9 @@ public: /// \endcode /// Required for proper codegen of final assignment performed by the /// lastprivate clause. + /// \param LPKind Lastprivate kind, e.g. 'conditional'. + /// \param LPKindLoc Location of the lastprivate kind. + /// \param ColonLoc Location of the ':' symbol if lastprivate kind is used. /// \param PreInit Statement that must be executed before entering the OpenMP /// region with this clause. /// \param PostUpdate Expression that must be executed after exit from the @@ -2250,7 +2273,8 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef SrcExprs, ArrayRef DstExprs, ArrayRef AssignmentOps, - Stmt *PreInit, Expr *PostUpdate); + OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, + SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate); /// Creates an empty clause with the place for \a N variables. /// @@ -2258,6 +2282,13 @@ public: /// \param N The number of variables. static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + /// Lastprivate kind. + OpenMPLastprivateModifier getKind() const { return LPKind; } + /// Returns the location of the lastprivate kind. + SourceLocation getKindLoc() const { return LPKindLoc; } + /// Returns the location of the ':' symbol, if any. + SourceLocation getColonLoc() const { return ColonLoc; } + using helper_expr_iterator = MutableArrayRef::iterator; using helper_expr_const_iterator = ArrayRef::iterator; using helper_expr_range = llvm::iterator_range; @@ -6240,6 +6271,102 @@ public: } }; +/// This represents clause 'nontemporal' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp simd nontemporal(a) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'nontemporal' for +/// the variable 'a'. +class OMPNontemporalClause final + : public OMPVarListClause, + private llvm::TrailingObjects { + friend class OMPClauseReader; + friend OMPVarListClause; + friend TrailingObjects; + + /// Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + OMPNontemporalClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause(OMPC_nontemporal, StartLoc, + LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + explicit OMPNontemporalClause(unsigned N) + : OMPVarListClause( + OMPC_nontemporal, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + + /// Get the list of privatied copies if the member expression was captured by + /// one of the privatization clauses. + MutableArrayRef getPrivateRefs() { + return MutableArrayRef(varlist_end(), varlist_size()); + } + ArrayRef getPrivateRefs() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + +public: + /// Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + static OMPNontemporalClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef VL); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + static OMPNontemporalClause *CreateEmpty(const ASTContext &C, unsigned N); + + /// Sets the list of references to private copies created in private clauses. + /// \param VL List of references. + void setPrivateRefs(ArrayRef VL); + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + const_child_range children() const { + auto Children = const_cast(this)->children(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range private_refs() { + return child_range(reinterpret_cast(getPrivateRefs().begin()), + reinterpret_cast(getPrivateRefs().end())); + } + + const_child_range private_refs() const { + auto Children = const_cast(this)->private_refs(); + return const_child_range(Children.begin(), Children.end()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_nontemporal; + } +}; + /// This class implements a simple visitor for OMPClause /// subclasses. template class Ptr, typename RetTy> diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 0cd62ba373d..80eec6a5a8b 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the PrinterHelper interface. +// This file defines helper types for AST pretty-printing. // //===----------------------------------------------------------------------===// @@ -29,6 +29,16 @@ public: virtual bool handledStmt(Stmt* E, raw_ostream& OS) = 0; }; +/// Callbacks to use to customize the behavior of the pretty-printer. +class PrintingCallbacks { +protected: + ~PrintingCallbacks() = default; + +public: + /// Remap a path to a form suitable for printing. + virtual std::string remapPath(StringRef Path) const { return Path; } +}; + /// Describes how types, statements, expressions, and declarations should be /// printed. /// @@ -50,7 +60,7 @@ struct PrintingPolicy { MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), FullyQualifiedName(false), - RemapFilePaths(false), PrintCanonicalTypes(false) {} + PrintCanonicalTypes(false) {} /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -224,14 +234,11 @@ struct PrintingPolicy { /// This is the opposite of SuppressScope and thus overrules it. unsigned FullyQualifiedName : 1; - /// Whether to apply -fdebug-prefix-map to any file paths. - unsigned RemapFilePaths : 1; - /// Whether to print types as written or canonically. unsigned PrintCanonicalTypes : 1; - /// When RemapFilePaths is true, this function performs the action. - std::function remapPath; + /// Callbacks to use to allow the behavior of printing to be customized. + const PrintingCallbacks *Callbacks = nullptr; }; } // end namespace clang diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td new file mode 100644 index 00000000000..9aacdb9fee3 --- /dev/null +++ b/clang/include/clang/AST/PropertiesBase.td @@ -0,0 +1,495 @@ +//==--- PropertiesBase.td - Baseline definitions for AST properties -------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +class HasProperties; + +/// The type of the property. +class PropertyType { + /// The C++ type name for the type. + string CXXName = !if(!ne(typeName, ""), typeName, NAME); + + /// Whether the C++ type should generally be passed around by reference. + bit PassByReference = 0; + + /// Whether `const` should be prepended to the type when writing. + bit ConstWhenWriting = 0; + + /// Given a value of type Optional bound as 'value', yield a + /// CXXName that can be serialized into a DataStreamTypeWriter. + string PackOptional = ""; + + /// Given a value of type CXXName bound as 'value' that was deserialized + /// by a DataStreamTypeReader, yield an Optional. + string UnpackOptional = ""; + + /// A list of types for which buffeers must be passed to the read + /// operations. + list BufferElementTypes = []; +} + +/// Property types that correspond to specific C++ enums. +class EnumPropertyType : PropertyType {} + +/// Property types that correspond to a specific C++ class. +/// Supports optional values by using the null representation. +class RefPropertyType : PropertyType { + let PackOptional = + "value ? *value : nullptr"; + let UnpackOptional = + "value ? llvm::Optional<" # CXXName # ">(value) : llvm::None"; +} + +/// Property types that correspond to a specific subclass of another type. +class SubclassPropertyType + : RefPropertyType { + PropertyType Base = base; + string SubclassName = className; + let ConstWhenWriting = base.ConstWhenWriting; +} + +/// Property types that support optional values by using their +/// default value. +class DefaultValuePropertyType : PropertyType { + let PackOptional = + "value ? *value : " # CXXName # "()"; + let UnpackOptional = + "value.isNull() ? llvm::None : llvm::Optional<" # CXXName # ">(value)"; +} + +/// Property types that correspond to integer types and support optional +/// values by shifting the value over by 1. +class CountPropertyType : PropertyType { + let PackOptional = + "value ? *value + 1 : 0"; + let UnpackOptional = + "value ? llvm::Optional<" # CXXName # ">(value - 1) : llvm::None"; +} + +def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; } +def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; } +def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">; +def AttrKind : EnumPropertyType<"attr::Kind">; +def AutoTypeKeyword : EnumPropertyType; +def Bool : PropertyType<"bool">; +def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">; +def CallingConv : EnumPropertyType; +def DeclarationName : PropertyType; +def DeclarationNameKind : EnumPropertyType<"DeclarationName::NameKind">; +def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; } + def CXXRecordDeclRef : + SubclassPropertyType<"CXXRecordDecl", DeclRef>; + def FunctionDeclRef : + SubclassPropertyType<"FunctionDecl", DeclRef>; + def NamedDeclRef : + SubclassPropertyType<"NamedDecl", DeclRef>; + def NamespaceDeclRef : + SubclassPropertyType<"NamespaceDecl", DeclRef>; + def NamespaceAliasDeclRef : + SubclassPropertyType<"NamespaceAliasDecl", DeclRef>; + def ObjCProtocolDeclRef : + SubclassPropertyType<"ObjCProtocolDecl", DeclRef>; + def ObjCTypeParamDeclRef : + SubclassPropertyType<"ObjCTypeParamDecl", DeclRef>; + def TagDeclRef : + SubclassPropertyType<"TagDecl", DeclRef>; + def TemplateDeclRef : + SubclassPropertyType<"TemplateDecl", DeclRef>; + def TemplateTypeParmDeclRef : + SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>; + def TemplateTemplateParmDeclRef : + SubclassPropertyType<"TemplateTemplateParmDecl", DeclRef>; + def ValueDeclRef : + SubclassPropertyType<"ValueDecl", DeclRef>; +def ElaboratedTypeKeyword : EnumPropertyType; +def ExtParameterInfo : PropertyType<"FunctionProtoType::ExtParameterInfo">; +def Identifier : RefPropertyType<"IdentifierInfo"> { let ConstWhenWriting = 1; } +def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">; +def NestedNameSpecifierKind : + EnumPropertyType<"NestedNameSpecifier::SpecifierKind">; +def OverloadedOperatorKind : EnumPropertyType; +def Qualifiers : PropertyType; +def QualType : DefaultValuePropertyType; +def RefQualifierKind : EnumPropertyType; +def Selector : PropertyType; +def SourceLocation : PropertyType; +def StmtRef : RefPropertyType<"Stmt"> { let ConstWhenWriting = 1; } + def ExprRef : SubclassPropertyType<"Expr", StmtRef>; +def TemplateArgument : PropertyType; +def TemplateArgumentKind : EnumPropertyType<"TemplateArgument::ArgKind">; +def TemplateName : DefaultValuePropertyType; +def TemplateNameKind : EnumPropertyType<"TemplateName::NameKind">; +def UInt32 : CountPropertyType<"uint32_t">; +def UInt64 : CountPropertyType<"uint64_t">; +def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">; +def VectorKind : EnumPropertyType<"VectorType::VectorKind">; + +def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> { + let BufferElementTypes = [ QualType ]; +} + +/// Arrays. The corresponding C++ type is ArrayRef of the corresponding +/// C++ type of the element. +class Array : PropertyType { + PropertyType Element = element; + let BufferElementTypes = [ element ]; +} + +/// llvm::Optional. The corresponding C++ type is generally just the +/// corresponding C++ type of the element. +/// +/// Optional may restrict the range of the operand for some +/// serialization clients. +class Optional : PropertyType { + PropertyType Element = element; + let PassByReference = element.PassByReference; +} + +/// A property of an AST node. +class Property { + HasProperties Class; + string Name = name; + PropertyType Type = type; + + /// A function for reading the property, expressed in terms of a variable + /// "node". + code Read; + + /// Code specifying when this property is available. Can be defined + /// in terms of other properties, in which case this property must be + /// read/written after those properties. Using this will make the + /// value Optional when deserializing. + /// + /// FIXME: the emitter doesn't yet force dependent properties to be + /// read/written later; this only works if the properties used in the + /// condition happen to be written first. + code Conditional = ""; +} + +/// A rule for declaring helper variables when read properties from a +/// value of this type. Note that this means that this code is actually +/// run when *writing* values of this type; however, naming this +/// `ReadHelper` makes the connection to the `Read` operations on the +/// properties much clearer. +class ReadHelper { + HasProperties Class; + + /// Code which will be run when writing objects of this type before + /// writing any of the properties, specified in terms of a variable + /// `node`. + code Code = _code; +} + +/// A rule for creating objects of this type. +class Creator { + HasProperties Class; + + /// A function for creating values of this kind, expressed in terms of a + /// variable `ctx` of type `ASTContext &`. Must also refer to all of the + /// properties by name. + code Create = create; +} + +/// A rule which overrides some of the normal rules. +class Override { + HasProperties Class; + + /// Properties from base classes that should be ignored. + list IgnoredProperties = []; +} + +/// A description of how to break a type into cases. Providing this and +/// an exhaustive list of the cases will cause AbstractBasic{Reader,Writer} +/// to be generated with a default implementation of how to read the +/// type. +/// +/// Creator rules for the cases can additionally access a variable +/// `kind` of the KindType. +class PropertyTypeKind { + /// The type for which this describes cases. + PropertyType Type = type; + + /// The type of this type's kind enum. + PropertyType KindType = kindType; + + /// The property name to use for the kind. + string KindPropertyName = "kind"; + + /// An expression which reads the kind from a value, expressed in terms + /// of a variable `node`. + string Read = readCode; +} + +/// One of the options for representing a particular type. +class PropertyTypeCase : HasProperties { + /// The type of which this is a case. + PropertyType Type = type; + + /// The name of the case (a value of the type's kind enum). + string Name = name; +} + +// Type cases for DeclarationName. +def : PropertyTypeKind; +let Class = PropertyTypeCase in { + def : Property<"identifier", Identifier> { + let Read = [{ node.getAsIdentifierInfo() }]; + } + def : Creator<[{ + return DeclarationName(identifier); + }]>; +} +foreach count = ["Zero", "One", "Multi"] in { + let Class = PropertyTypeCase in { + def : Property<"selector", Selector> { + let Read = [{ node.getObjCSelector() }]; + } + def : Creator<[{ + return DeclarationName(selector); + }]>; + } +} +foreach kind = ["Constructor", "Destructor", "ConversionFunction"] in { + let Class = PropertyTypeCase in { + def : Property<"type", QualType> { + let Read = [{ node.getCXXNameType() }]; + } + def : Creator<[{ + return ctx.DeclarationNames.getCXX}]#kind#[{Name( + ctx.getCanonicalType(type)); + }]>; + } +} +let Class = PropertyTypeCase in { + def : Property<"declaration", TemplateDeclRef> { + let Read = [{ node.getCXXDeductionGuideTemplate() }]; + } + def : Creator<[{ + return ctx.DeclarationNames.getCXXDeductionGuideName(declaration); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"operatorKind", OverloadedOperatorKind> { + let Read = [{ node.getCXXOverloadedOperator() }]; + } + def : Creator<[{ + return ctx.DeclarationNames.getCXXOperatorName(operatorKind); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"identifier", Identifier> { + let Read = [{ node.getCXXLiteralIdentifier() }]; + } + def : Creator<[{ + return ctx.DeclarationNames.getCXXLiteralOperatorName(identifier); + }]>; +} +let Class = PropertyTypeCase in { + def : Creator<[{ + return DeclarationName::getUsingDirectiveName(); + }]>; +} + +// Type cases for TemplateName. +def : PropertyTypeKind; +let Class = PropertyTypeCase in { + def : Property<"declaration", TemplateDeclRef> { + let Read = [{ node.getAsTemplateDecl() }]; + } + def : Creator<[{ + return TemplateName(declaration); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"overloads", Array> { + let Read = [{ node.getAsOverloadedTemplate()->decls() }]; + } + def : Creator<[{ + // Copy into an UnresolvedSet to satisfy the interface. + UnresolvedSet<8> overloadSet; + for (auto overload : overloads) { + overloadSet.addDecl(overload); + } + + return ctx.getOverloadedTemplateName(overloadSet.begin(), + overloadSet.end()); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"name", DeclarationName> { + let Read = [{ node.getAsAssumedTemplateName()->getDeclName() }]; + } + def : Creator<[{ + return ctx.getAssumedTemplateName(name); + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto qtn = node.getAsQualifiedTemplateName(); + }]>; + def : Property<"qualifier", NestedNameSpecifier> { + let Read = [{ qtn->getQualifier() }]; + } + def : Property<"hasTemplateKeyword", Bool> { + let Read = [{ qtn->hasTemplateKeyword() }]; + } + def : Property<"declaration", TemplateDeclRef> { + let Read = [{ qtn->getTemplateDecl() }]; + } + def : Creator<[{ + return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword, + declaration); + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto dtn = node.getAsDependentTemplateName(); + }]>; + def : Property<"qualifier", NestedNameSpecifier> { + let Read = [{ dtn->getQualifier() }]; + } + def : Property<"identifier", Optional> { + let Read = [{ makeOptionalFromPointer( + dtn->isIdentifier() + ? dtn->getIdentifier() + : nullptr) }]; + } + def : Property<"operatorKind", OverloadedOperatorKind> { + let Conditional = [{ !identifier }]; + let Read = [{ dtn->getOperator() }]; + } + def : Creator<[{ + if (identifier) { + return ctx.getDependentTemplateName(qualifier, *identifier); + } else { + return ctx.getDependentTemplateName(qualifier, *operatorKind); + } + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto parm = node.getAsSubstTemplateTemplateParm(); + }]>; + def : Property<"parameter", TemplateTemplateParmDeclRef> { + let Read = [{ parm->getParameter() }]; + } + def : Property<"replacement", TemplateName> { + let Read = [{ parm->getReplacement() }]; + } + def : Creator<[{ + return ctx.getSubstTemplateTemplateParm(parameter, replacement); + }]>; +} +let Class = PropertyTypeCase in { + def : ReadHelper<[{ + auto parm = node.getAsSubstTemplateTemplateParmPack(); + }]>; + def : Property<"parameterPack", TemplateTemplateParmDeclRef> { + let Read = [{ parm->getParameterPack() }]; + } + def : Property<"argumentPack", TemplateArgument> { + let Read = [{ parm->getArgumentPack() }]; + } + def : Creator<[{ + return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack); + }]>; +} + +// Type cases for TemplateArgument. +def : PropertyTypeKind; +let Class = PropertyTypeCase in { + def : Creator<[{ + return TemplateArgument(); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"type", QualType> { + let Read = [{ node.getAsType() }]; + } + def : Creator<[{ + return TemplateArgument(type); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"declaration", ValueDeclRef> { + let Read = [{ node.getAsDecl() }]; + } + def : Property<"parameterType", QualType> { + let Read = [{ node.getParamTypeForDecl() }]; + } + def : Creator<[{ + return TemplateArgument(declaration, parameterType); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"type", QualType> { + let Read = [{ node.getNullPtrType() }]; + } + def : Creator<[{ + return TemplateArgument(type, /*nullptr*/ true); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"value", APSInt> { + let Read = [{ node.getAsIntegral() }]; + } + def : Property<"type", QualType> { + let Read = [{ node.getIntegralType() }]; + } + def : Creator<[{ + return TemplateArgument(ctx, value, type); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"name", TemplateName> { + let Read = [{ node.getAsTemplateOrTemplatePattern() }]; + } + def : Creator<[{ + return TemplateArgument(name); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"name", TemplateName> { + let Read = [{ node.getAsTemplateOrTemplatePattern() }]; + } + def : Property<"numExpansions", Optional> { + let Read = [{ + // Translate unsigned -> uint32_t just in case. + node.getNumTemplateExpansions().map( + [](unsigned i) { return uint32_t(i); }) + }]; + } + def : Creator<[{ + auto numExpansionsUnsigned = + numExpansions.map([](uint32_t i) { return unsigned(i); }); + return TemplateArgument(name, numExpansionsUnsigned); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"expression", ExprRef> { + let Read = [{ node.getAsExpr() }]; + } + def : Creator<[{ + return TemplateArgument(expression); + }]>; +} +let Class = PropertyTypeCase in { + def : Property<"elements", Array> { + let Read = [{ node.pack_elements() }]; + } + def : Creator<[{ + // Copy the pack into the ASTContext. + TemplateArgument *ctxElements = new (ctx) TemplateArgument[elements.size()]; + for (size_t i = 0, e = elements.size(); i != e; ++i) + ctxElements[i] = elements[i]; + return TemplateArgument(llvm::makeArrayRef(ctxElements, elements.size())); + }]>; +} diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 5b58eab95d6..f8ab8e451d8 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -304,6 +304,11 @@ public: bool TraverseSynOrSemInitListExpr(InitListExpr *S, DataRecursionQueue *Queue = nullptr); + /// Recursively visit a reference to a concept with potential arguments. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseConceptReference(const ConceptReference &C); + // ---- Methods on Attrs ---- // Visit an attribute. @@ -1162,11 +1167,13 @@ DEF_TRAVERSE_TYPELOC(LValueReferenceType, DEF_TRAVERSE_TYPELOC(RValueReferenceType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) -// FIXME: location of base class? // We traverse this in the type case as well, but how is it not reached through // the pointee type? DEF_TRAVERSE_TYPELOC(MemberPointerType, { - TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); + if (auto *TSI = TL.getClassTInfo()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + else + TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) @@ -1435,6 +1442,10 @@ DEF_TRAVERSE_DECL(CapturedDecl, { DEF_TRAVERSE_DECL(EmptyDecl, {}) +DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, { + TRY_TO(TraverseStmt(D->getTemporaryExpr())); +}) + DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) @@ -1767,9 +1778,8 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like // template