aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/Decl.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Decl.h')
-rw-r--r--include/clang/AST/Decl.h311
1 files changed, 134 insertions, 177 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e06b58b37be2..046ce70a343b 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -21,11 +21,13 @@
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TrailingObjects.h"
namespace clang {
struct ASTTemplateArgumentListInfo;
@@ -37,7 +39,6 @@ class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class LabelStmt;
class MemberSpecializationInfo;
-class Module;
class NestedNameSpecifier;
class ParmVarDecl;
class Stmt;
@@ -318,7 +319,8 @@ public:
NamedDecl *getUnderlyingDecl() {
// Fast-path the common case.
if (this->getKind() != UsingShadow &&
- this->getKind() != ObjCCompatibleAlias)
+ this->getKind() != ObjCCompatibleAlias &&
+ this->getKind() != NamespaceAlias)
return this;
return getUnderlyingDeclImpl();
@@ -462,25 +464,15 @@ public:
}
/// \brief Get the original (first) namespace declaration.
- NamespaceDecl *getOriginalNamespace() {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ NamespaceDecl *getOriginalNamespace();
/// \brief Get the original (first) namespace declaration.
- const NamespaceDecl *getOriginalNamespace() const {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ const NamespaceDecl *getOriginalNamespace() const;
/// \brief Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
- bool isOriginalNamespace() const { return isFirstDecl(); }
+ bool isOriginalNamespace() const;
/// \brief Retrieve the anonymous namespace nested inside this namespace,
/// if any.
@@ -572,8 +564,7 @@ struct QualifierInfo {
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ ArrayRef<TemplateParameterList *> TPLists);
private:
// Copy constructor and copy assignment are disabled.
@@ -658,8 +649,8 @@ public:
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
SourceLocation getTypeSpecStartLoc() const;
@@ -728,17 +719,14 @@ public:
};
protected:
- /// \brief Placeholder type used in Init to denote an unparsed C++ default
- /// argument.
- struct UnparsedDefaultArgument;
-
- /// \brief Placeholder type used in Init to denote an uninstantiated C++
- /// default argument.
- struct UninstantiatedDefaultArgument;
-
- typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
- UnparsedDefaultArgument *,
- UninstantiatedDefaultArgument *> InitType;
+ // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
+ // have allocated the auxilliary struct of information there.
+ //
+ // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
+ // this as *many* VarDecls are ParmVarDecls that don't have default
+ // arguments. We could save some space by moving this pointer union to be
+ // allocated in trailing space when necessary.
+ typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
/// \brief The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
@@ -762,6 +750,13 @@ private:
protected:
enum { NumParameterIndexBits = 8 };
+ enum DefaultArgKind {
+ DAK_None,
+ DAK_Unparsed,
+ DAK_Uninstantiated,
+ DAK_Normal
+ };
+
class ParmVarDeclBitfields {
friend class ParmVarDecl;
friend class ASTDeclReader;
@@ -772,6 +767,12 @@ protected:
/// prior declaration.
unsigned HasInheritedDefaultArg : 1;
+ /// Describes the kind of default argument for this parameter. By default
+ /// this is none. If this is normal, then the default argument is stored in
+ /// the \c VarDecl initalizer expression unless we were unble to parse
+ /// (even an invalid) expression for the default argument.
+ unsigned DefaultArgKind : 2;
+
/// Whether this parameter undergoes K&R argument promotion.
unsigned IsKNRPromoted : 1;
@@ -815,6 +816,9 @@ protected:
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
+ /// \brief Whether this variable is a (C++ Concepts TS) concept.
+ unsigned IsConcept : 1;
+
/// \brief Whether this variable is the implicit variable for a lambda
/// init-capture.
unsigned IsInitCapture : 1;
@@ -1062,47 +1066,14 @@ public:
/// declaration it is attached to. Also get that declaration.
const Expr *getAnyInitializer(const VarDecl *&D) const;
- bool hasInit() const {
- return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
- }
+ bool hasInit() const;
const Expr *getInit() const {
- if (Init.isNull())
- return nullptr;
-
- const Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
- return (const Expr*) S;
- }
- Expr *getInit() {
- if (Init.isNull())
- return nullptr;
-
- Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
-
- return (Expr*) S;
+ return const_cast<VarDecl *>(this)->getInit();
}
+ Expr *getInit();
/// \brief Retrieve the address of the initializer expression.
- Stmt **getInitAddress() {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- return &ES->Value;
-
- // This union hack tip-toes around strict-aliasing rules.
- union {
- InitType *InitPtr;
- Stmt **StmtPtr;
- };
-
- InitPtr = &Init;
- return StmtPtr;
- }
+ Stmt **getInitAddress();
void setInit(Expr *I);
@@ -1124,33 +1095,18 @@ public:
/// \brief Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
/// to untyped APValue if the value could not be evaluated.
- APValue *getEvaluatedValue() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- if (Eval->WasEvaluated)
- return &Eval->Evaluated;
-
- return nullptr;
- }
+ APValue *getEvaluatedValue() const;
/// \brief Determines whether it is already known whether the
/// initializer is an integral constant expression or not.
- bool isInitKnownICE() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- return Eval->CheckedICE;
-
- return false;
- }
+ bool isInitKnownICE() const;
/// \brief Determines whether the initializer is an integral constant
/// expression, or in C++11, whether the initializer is a constant
/// expression.
///
/// \pre isInitKnownICE()
- bool isInitICE() const {
- assert(isInitKnownICE() &&
- "Check whether we already know that the initializer is an ICE");
- return Init.get<EvaluatedStmt *>()->IsICE;
- }
+ bool isInitICE() const;
/// \brief Determine whether the value of the initializer attached to this
/// declaration is an integral constant expression.
@@ -1238,6 +1194,15 @@ public:
NonParmVarDeclBits.IsConstexpr = IC;
}
+ /// Whether this variable is (C++ Concepts TS) concept.
+ bool isConcept() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept;
+ }
+ void setConcept(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsConcept = IC;
+ }
+
/// Whether this variable is the implicit variable for a lambda init-capture.
bool isInitCapture() const {
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
@@ -1342,6 +1307,7 @@ protected:
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
+ assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
assert(ParmVarDeclBits.IsKNRPromoted == false);
assert(ParmVarDeclBits.IsObjCMethodParam == false);
setDefaultArg(DefArg);
@@ -1416,29 +1382,20 @@ public:
return const_cast<ParmVarDecl *>(this)->getDefaultArg();
}
- void setDefaultArg(Expr *defarg) {
- Init = reinterpret_cast<Stmt *>(defarg);
- }
+ void setDefaultArg(Expr *defarg);
/// \brief Retrieve the source range that covers the entire default
/// argument.
SourceRange getDefaultArgRange() const;
- void setUninstantiatedDefaultArg(Expr *arg) {
- Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
- }
- Expr *getUninstantiatedDefaultArg() {
- return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
- }
+ void setUninstantiatedDefaultArg(Expr *arg);
+ Expr *getUninstantiatedDefaultArg();
const Expr *getUninstantiatedDefaultArg() const {
- return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
}
/// hasDefaultArg - Determines whether this parameter has a default argument,
/// either parsed or not.
- bool hasDefaultArg() const {
- return getInit() || hasUnparsedDefaultArg() ||
- hasUninstantiatedDefaultArg();
- }
+ bool hasDefaultArg() const;
/// hasUnparsedDefaultArg - Determines whether this parameter has a
/// default argument that has not yet been parsed. This will occur
@@ -1451,11 +1408,11 @@ public:
/// }; // x has a regular default argument now
/// @endcode
bool hasUnparsedDefaultArg() const {
- return Init.is<UnparsedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
}
bool hasUninstantiatedDefaultArg() const {
- return Init.is<UninstantiatedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
}
/// setUnparsedDefaultArg - Specify that this parameter has an
@@ -1463,7 +1420,9 @@ public:
/// real default argument via setDefaultArg when the class
/// definition enclosing the function declaration that owns this
/// default argument is completed.
- void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; }
+ void setUnparsedDefaultArg() {
+ ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
+ }
bool hasInheritedDefaultArg() const {
return ParmVarDeclBits.HasInheritedDefaultArg;
@@ -1546,25 +1505,25 @@ private:
LazyDeclStmtPtr Body;
- // FIXME: This can be packed into the bitfields in Decl.
- // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ // FIXME: This can be packed into the bitfields in DeclContext.
+ // NOTE: VC++ packs bitfields poorly if the types differ.
unsigned SClass : 2;
- bool IsInline : 1;
- bool IsInlineSpecified : 1;
- bool IsVirtualAsWritten : 1;
- bool IsPure : 1;
- bool HasInheritedPrototype : 1;
- bool HasWrittenPrototype : 1;
- bool IsDeleted : 1;
- bool IsTrivial : 1; // sunk from CXXMethodDecl
- bool IsDefaulted : 1; // sunk from CXXMethoDecl
- bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
- bool HasImplicitReturnZero : 1;
- bool IsLateTemplateParsed : 1;
- bool IsConstexpr : 1;
+ unsigned IsInline : 1;
+ unsigned IsInlineSpecified : 1;
+ unsigned IsVirtualAsWritten : 1;
+ unsigned IsPure : 1;
+ unsigned HasInheritedPrototype : 1;
+ unsigned HasWrittenPrototype : 1;
+ unsigned IsDeleted : 1;
+ unsigned IsTrivial : 1; // sunk from CXXMethodDecl
+ unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
+ unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
+ unsigned HasImplicitReturnZero : 1;
+ unsigned IsLateTemplateParsed : 1;
+ unsigned IsConstexpr : 1;
/// \brief Indicates if the function uses __try.
- bool UsesSEHTry : 1;
+ unsigned UsesSEHTry : 1;
/// \brief Indicates if the function was a definition but its body was
/// skipped.
@@ -1835,7 +1794,7 @@ public:
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
- /// Whether this is a (C++11) constexpr function or constexpr constructor.
+ /// \brief Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
@@ -2084,9 +2043,7 @@ public:
/// \brief If this function is an instantiation of a member function of a
/// class template specialization, retrieves the member specialization
/// information.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- }
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
/// \brief Specify that this record is an instantiation of the
/// member function FD.
@@ -2107,13 +2064,9 @@ public:
/// FunctionDecl that describes the function template,
/// getDescribedFunctionTemplate() retrieves the
/// FunctionTemplateDecl from a FunctionDecl.
- FunctionTemplateDecl *getDescribedFunctionTemplate() const {
- return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>();
- }
+ FunctionTemplateDecl *getDescribedFunctionTemplate() const;
- void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
- TemplateOrSpecialization = Template;
- }
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
/// \brief Determine whether this function is a function template
/// specialization.
@@ -2128,10 +2081,7 @@ public:
/// \brief If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
/// Otherwise, returns NULL.
- FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<FunctionTemplateSpecializationInfo*>();
- }
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
/// \brief Determines whether this function is a function template
/// specialization or a member of a class template specialization that can
@@ -2208,10 +2158,7 @@ public:
const TemplateArgumentListInfo &TemplateArgs);
DependentFunctionTemplateSpecializationInfo *
- getDependentSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<DependentFunctionTemplateSpecializationInfo*>();
- }
+ getDependentSpecializationInfo() const;
/// \brief Determine what kind of template instantiation this function
/// represents.
@@ -2487,7 +2434,8 @@ public:
/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
-class IndirectFieldDecl : public ValueDecl {
+class IndirectFieldDecl : public ValueDecl,
+ public Mergeable<IndirectFieldDecl> {
void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
@@ -2525,6 +2473,9 @@ public:
return dyn_cast<VarDecl>(*chain_begin());
}
+ IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == IndirectField; }
@@ -2762,12 +2713,12 @@ private:
/// declaration specifier for variables, it points to the first VarDecl (used
/// for mangling);
/// otherwise, it is a null (TypedefNameDecl) pointer.
- llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier;
+ llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;
- bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); }
- ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); }
+ bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
+ ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
const ExtInfo *getExtInfo() const {
- return NamedDeclOrQualifier.get<ExtInfo *>();
+ return TypedefNameDeclOrQualifier.get<ExtInfo *>();
}
protected:
@@ -2778,7 +2729,7 @@ protected:
TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
IsEmbeddedInDeclarator(false), IsFreeStanding(false),
IsCompleteDefinitionRequired(false),
- NamedDeclOrQualifier((NamedDecl *)nullptr) {
+ TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
setPreviousDecl(PrevDecl);
@@ -2925,22 +2876,11 @@ public:
return (getDeclName() || getTypedefNameForAnonDecl());
}
- bool hasDeclaratorForAnonDecl() const {
- return dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
- DeclaratorDecl *getDeclaratorForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
-
TypedefNameDecl *getTypedefNameForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
+ return hasExtInfo() ? nullptr
+ : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
}
- void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; }
-
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
/// \brief Retrieve the nested-name-specifier that qualifies the name of this
@@ -2967,8 +2907,8 @@ public:
assert(i < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[i];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3301,7 +3241,14 @@ public:
bool hasVolatileMember() const { return HasVolatileMember; }
void setHasVolatileMember (bool val) { HasVolatileMember = val; }
-
+
+ bool hasLoadedFieldsFromExternalStorage() const {
+ return LoadedFieldsFromExternalStorage;
+ }
+ void setHasLoadedFieldsFromExternalStorage(bool val) {
+ LoadedFieldsFromExternalStorage = val;
+ }
+
/// \brief Determines whether this declaration represents the
/// injected class name.
///
@@ -3475,7 +3422,7 @@ private:
Stmt *Body;
TypeSourceInfo *SignatureAsWritten;
- Capture *Captures;
+ const Capture *Captures;
unsigned NumCaptures;
unsigned ManglingNumber;
@@ -3581,10 +3528,8 @@ public:
bool capturesVariable(const VarDecl *var) const;
- void setCaptures(ASTContext &Context,
- const Capture *begin,
- const Capture *end,
- bool capturesCXXThis);
+ void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
+ bool CapturesCXXThis);
unsigned getBlockManglingNumber() const {
return ManglingNumber;
@@ -3613,7 +3558,15 @@ public:
/// \brief This represents the body of a CapturedStmt, and serves as its
/// DeclContext.
-class CapturedDecl : public Decl, public DeclContext {
+class CapturedDecl final
+ : public Decl,
+ public DeclContext,
+ private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
+protected:
+ size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
+ return NumParams;
+ }
+
private:
/// \brief The number of parameters to the outlined function.
unsigned NumParams;
@@ -3622,13 +3575,14 @@ private:
/// \brief The body of the outlined function.
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
- explicit CapturedDecl(DeclContext *DC, unsigned NumParams)
- : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
- NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { }
+ explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
+
+ ImplicitParamDecl *const *getParams() const {
+ return getTrailingObjects<ImplicitParamDecl *>();
+ }
- ImplicitParamDecl **getParams() const {
- return reinterpret_cast<ImplicitParamDecl **>(
- const_cast<CapturedDecl *>(this) + 1);
+ ImplicitParamDecl **getParams() {
+ return getTrailingObjects<ImplicitParamDecl *>();
}
public:
@@ -3637,11 +3591,11 @@ public:
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams);
- Stmt *getBody() const override { return BodyAndNothrow.getPointer(); }
- void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
+ Stmt *getBody() const override;
+ void setBody(Stmt *B);
- bool isNothrow() const { return BodyAndNothrow.getInt(); }
- void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); }
+ bool isNothrow() const;
+ void setNothrow(bool Nothrow = true);
unsigned getNumParams() const { return NumParams; }
@@ -3666,7 +3620,7 @@ public:
}
unsigned getContextParamPosition() const { return ContextParam; }
- typedef ImplicitParamDecl **param_iterator;
+ typedef ImplicitParamDecl *const *param_iterator;
typedef llvm::iterator_range<param_iterator> param_range;
/// \brief Retrieve an iterator pointing to the first parameter decl.
@@ -3689,6 +3643,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// \brief Describes a module import declaration, which makes the contents
@@ -3701,7 +3656,8 @@ public:
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
-class ImportDecl : public Decl {
+class ImportDecl final : public Decl,
+ llvm::TrailingObjects<ImportDecl, SourceLocation> {
/// \brief The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
@@ -3717,7 +3673,8 @@ class ImportDecl : public Decl {
friend class ASTReader;
friend class ASTDeclReader;
friend class ASTContext;
-
+ friend TrailingObjects;
+
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);