summaryrefslogtreecommitdiff
path: root/include/clang/AST/DeclCXX.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclCXX.h')
-rw-r--r--include/clang/AST/DeclCXX.h409
1 files changed, 295 insertions, 114 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 7c54901be3ea5..66acfee60db05 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -16,6 +16,7 @@
#ifndef LLVM_CLANG_AST_DECLCXX_H
#define LLVM_CLANG_AST_DECLCXX_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
@@ -29,6 +30,7 @@ namespace clang {
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
+class ConstructorUsingShadowDecl;
class CXXBasePath;
class CXXBasePaths;
class CXXConstructorDecl;
@@ -165,13 +167,13 @@ class CXXBaseSpecifier {
SourceLocation EllipsisLoc;
/// \brief Whether this is a virtual base class or not.
- bool Virtual : 1;
+ unsigned Virtual : 1;
/// \brief Whether this is the base of a class (true) or of a struct (false).
///
/// This determines the mapping from the access specifier as written in the
/// source code to the access specifier used for semantic analysis.
- bool BaseOfClass : 1;
+ unsigned BaseOfClass : 1;
/// \brief Access specifier as written in the source code (may be AS_none).
///
@@ -181,7 +183,7 @@ class CXXBaseSpecifier {
/// \brief Whether the class contains a using declaration
/// to inherit the named class's constructors.
- bool InheritConstructors : 1;
+ unsigned InheritConstructors : 1;
/// \brief The type of the base class.
///
@@ -257,30 +259,6 @@ public:
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
-/// \brief A lazy pointer to the definition data for a declaration.
-/// FIXME: This is a little CXXRecordDecl-specific that the moment.
-template<typename Decl, typename T> class LazyDefinitionDataPtr {
- llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl;
-
- LazyDefinitionDataPtr update() {
- if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) {
- if (Canon->isCanonicalDecl())
- Canon->getMostRecentDecl();
- else
- // Declaration isn't canonical any more;
- // update it and perform path compression.
- *this = Canon->getPreviousDecl()->DefinitionData.update();
- }
- return *this;
- }
-
-public:
- LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {}
- LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {}
- T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); }
- T *get() { return update().getNotUpdated(); }
-};
-
/// \brief Represents a C++ struct/union/class.
class CXXRecordDecl : public RecordDecl {
@@ -301,30 +279,30 @@ class CXXRecordDecl : public RecordDecl {
DefinitionData(CXXRecordDecl *D);
/// \brief True if this class has any user-declared constructors.
- bool UserDeclaredConstructor : 1;
+ unsigned UserDeclaredConstructor : 1;
/// \brief The user-declared special members which this class has.
unsigned UserDeclaredSpecialMembers : 6;
/// \brief True when this class is an aggregate.
- bool Aggregate : 1;
+ unsigned Aggregate : 1;
/// \brief True when this class is a POD-type.
- bool PlainOldData : 1;
+ unsigned PlainOldData : 1;
/// true when this class is empty for traits purposes,
/// i.e. has no data members other than 0-width bit-fields, has no
/// virtual function/base, and doesn't inherit from a non-empty
/// class. Doesn't take union-ness into account.
- bool Empty : 1;
+ unsigned Empty : 1;
/// \brief True when this class is polymorphic, i.e., has at
/// least one virtual member or derives from a polymorphic class.
- bool Polymorphic : 1;
+ unsigned Polymorphic : 1;
/// \brief True when this class is abstract, i.e., has at least
/// one pure virtual function, (that can come from a base class).
- bool Abstract : 1;
+ unsigned Abstract : 1;
/// \brief True when this class has standard layout.
///
@@ -340,58 +318,70 @@ class CXXRecordDecl : public RecordDecl {
/// classes with non-static data members, and
/// * has no base classes of the same type as the first non-static data
/// member.
- bool IsStandardLayout : 1;
+ unsigned IsStandardLayout : 1;
/// \brief True when there are no non-empty base classes.
///
/// This is a helper bit of state used to implement IsStandardLayout more
/// efficiently.
- bool HasNoNonEmptyBases : 1;
+ unsigned HasNoNonEmptyBases : 1;
/// \brief True when there are private non-static data members.
- bool HasPrivateFields : 1;
+ unsigned HasPrivateFields : 1;
/// \brief True when there are protected non-static data members.
- bool HasProtectedFields : 1;
+ unsigned HasProtectedFields : 1;
/// \brief True when there are private non-static data members.
- bool HasPublicFields : 1;
+ unsigned HasPublicFields : 1;
/// \brief True if this class (or any subobject) has mutable fields.
- bool HasMutableFields : 1;
+ unsigned HasMutableFields : 1;
/// \brief True if this class (or any nested anonymous struct or union)
/// has variant members.
- bool HasVariantMembers : 1;
+ unsigned HasVariantMembers : 1;
/// \brief True if there no non-field members declared by the user.
- bool HasOnlyCMembers : 1;
+ unsigned HasOnlyCMembers : 1;
/// \brief True if any field has an in-class initializer, including those
/// within anonymous unions or structs.
- bool HasInClassInitializer : 1;
+ unsigned HasInClassInitializer : 1;
/// \brief True if any field is of reference type, and does not have an
/// in-class initializer.
///
/// In this case, value-initialization of this class is illegal in C++98
/// even if the class has a trivial default constructor.
- bool HasUninitializedReferenceMember : 1;
+ unsigned HasUninitializedReferenceMember : 1;
+
+ /// \brief True if any non-mutable field whose type doesn't have a user-
+ /// provided default ctor also doesn't have an in-class initializer.
+ unsigned HasUninitializedFields : 1;
+
+ /// \brief True if there are any member using-declarations that inherit
+ /// constructors from a base class.
+ unsigned HasInheritedConstructor : 1;
+
+ /// \brief True if there are any member using-declarations named
+ /// 'operator='.
+ unsigned HasInheritedAssignment : 1;
/// \brief These flags are \c true if a defaulted corresponding special
/// member can't be fully analyzed without performing overload resolution.
/// @{
- bool NeedOverloadResolutionForMoveConstructor : 1;
- bool NeedOverloadResolutionForMoveAssignment : 1;
- bool NeedOverloadResolutionForDestructor : 1;
+ unsigned NeedOverloadResolutionForMoveConstructor : 1;
+ unsigned NeedOverloadResolutionForMoveAssignment : 1;
+ unsigned NeedOverloadResolutionForDestructor : 1;
/// @}
/// \brief These flags are \c true if an implicit defaulted corresponding
/// special member would be defined as deleted.
/// @{
- bool DefaultedMoveConstructorIsDeleted : 1;
- bool DefaultedMoveAssignmentIsDeleted : 1;
- bool DefaultedDestructorIsDeleted : 1;
+ unsigned DefaultedMoveConstructorIsDeleted : 1;
+ unsigned DefaultedMoveAssignmentIsDeleted : 1;
+ unsigned DefaultedDestructorIsDeleted : 1;
/// @}
/// \brief The trivial special members which this class has, per
@@ -411,33 +401,37 @@ class CXXRecordDecl : public RecordDecl {
unsigned DeclaredNonTrivialSpecialMembers : 6;
/// \brief True when this class has a destructor with no semantic effect.
- bool HasIrrelevantDestructor : 1;
+ unsigned HasIrrelevantDestructor : 1;
/// \brief True when this class has at least one user-declared constexpr
/// constructor which is neither the copy nor move constructor.
- bool HasConstexprNonCopyMoveConstructor : 1;
+ unsigned HasConstexprNonCopyMoveConstructor : 1;
+
+ /// \brief True if this class has a (possibly implicit) defaulted default
+ /// constructor.
+ unsigned HasDefaultedDefaultConstructor : 1;
/// \brief True if a defaulted default constructor for this class would
/// be constexpr.
- bool DefaultedDefaultConstructorIsConstexpr : 1;
+ unsigned DefaultedDefaultConstructorIsConstexpr : 1;
/// \brief True if this class has a constexpr default constructor.
///
/// This is true for either a user-declared constexpr default constructor
/// or an implicitly declared constexpr default constructor.
- bool HasConstexprDefaultConstructor : 1;
+ unsigned HasConstexprDefaultConstructor : 1;
/// \brief True when this class contains at least one non-static data
/// member or base class of non-literal or volatile type.
- bool HasNonLiteralTypeFieldsOrBases : 1;
+ unsigned HasNonLiteralTypeFieldsOrBases : 1;
/// \brief True when visible conversion functions are already computed
/// and are available.
- bool ComputedVisibleConversions : 1;
+ unsigned ComputedVisibleConversions : 1;
/// \brief Whether we have a C++11 user-provided default constructor (not
/// explicitly deleted or defaulted).
- bool UserProvidedDefaultConstructor : 1;
+ unsigned UserProvidedDefaultConstructor : 1;
/// \brief The special members which have been declared for this class,
/// either by the user or implicitly.
@@ -445,25 +439,25 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Whether an implicit copy constructor would have a const-qualified
/// parameter.
- bool ImplicitCopyConstructorHasConstParam : 1;
+ unsigned ImplicitCopyConstructorHasConstParam : 1;
/// \brief Whether an implicit copy assignment operator would have a
/// const-qualified parameter.
- bool ImplicitCopyAssignmentHasConstParam : 1;
+ unsigned ImplicitCopyAssignmentHasConstParam : 1;
/// \brief Whether any declared copy constructor has a const-qualified
/// parameter.
- bool HasDeclaredCopyConstructorWithConstParam : 1;
+ unsigned HasDeclaredCopyConstructorWithConstParam : 1;
/// \brief Whether any declared copy assignment operator has either a
/// const-qualified reference parameter or a non-reference parameter.
- bool HasDeclaredCopyAssignmentWithConstParam : 1;
+ unsigned HasDeclaredCopyAssignmentWithConstParam : 1;
/// \brief Whether this class describes a C++ lambda.
- bool IsLambda : 1;
+ unsigned IsLambda : 1;
/// \brief Whether we are currently parsing base specifiers.
- bool IsParsingBaseSpecifiers : 1;
+ unsigned IsParsingBaseSpecifiers : 1;
/// \brief The number of base class specifiers in Bases.
unsigned NumBases;
@@ -515,16 +509,19 @@ class CXXRecordDecl : public RecordDecl {
return getVBasesSlowCase();
}
+ ArrayRef<CXXBaseSpecifier> bases() const {
+ return llvm::makeArrayRef(getBases(), NumBases);
+ }
+ ArrayRef<CXXBaseSpecifier> vbases() const {
+ return llvm::makeArrayRef(getVBases(), NumVBases);
+ }
+
private:
CXXBaseSpecifier *getBasesSlowCase() const;
CXXBaseSpecifier *getVBasesSlowCase() const;
};
- typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>
- DefinitionDataPtr;
- friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>;
-
- mutable DefinitionDataPtr DefinitionData;
+ struct DefinitionData *DefinitionData;
/// \brief Describes a C++ closure type (generated by a lambda expression).
struct LambdaDefinitionData : public DefinitionData {
@@ -587,8 +584,14 @@ class CXXRecordDecl : public RecordDecl {
};
+ struct DefinitionData *dataPtr() const {
+ // Complete the redecl chain (if necessary).
+ getMostRecentDecl();
+ return DefinitionData;
+ }
+
struct DefinitionData &data() const {
- auto *DD = DefinitionData.get();
+ auto *DD = dataPtr();
assert(DD && "queried property of class with no definition");
return *DD;
}
@@ -596,7 +599,7 @@ class CXXRecordDecl : public RecordDecl {
struct LambdaDefinitionData &getLambdaData() const {
// No update required: a merged definition cannot change any lambda
// properties.
- auto *DD = DefinitionData.getNotUpdated();
+ auto *DD = DefinitionData;
assert(DD && DD->IsLambda && "queried lambda property of non-lambda class");
return static_cast<LambdaDefinitionData&>(*DD);
}
@@ -673,11 +676,13 @@ public:
}
CXXRecordDecl *getDefinition() const {
- auto *DD = DefinitionData.get();
+ // We only need an update if we don't already know which
+ // declaration is the definition.
+ auto *DD = DefinitionData ? DefinitionData : dataPtr();
return DD ? DD->Definition : nullptr;
}
- bool hasDefinition() const { return DefinitionData.get(); }
+ bool hasDefinition() const { return DefinitionData || dataPtr(); }
static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -1021,7 +1026,7 @@ public:
/// \brief Determine whether this class describes a lambda function object.
bool isLambda() const {
// An update record can't turn a non-lambda into a lambda.
- auto *DD = DefinitionData.getNotUpdated();
+ auto *DD = DefinitionData;
return DD && DD->IsLambda;
}
@@ -1136,9 +1141,10 @@ public:
/// \brief Determine whether this is an empty class in the sense of
/// (C++11 [meta.unary.prop]).
///
- /// A non-union class is empty iff it has a virtual function, virtual base,
- /// data member (other than 0-width bit-field) or inherits from a non-empty
- /// class.
+ /// The CXXRecordDecl is a class type, but not a union type,
+ /// with no non-static data members other than bit-fields of length 0,
+ /// no virtual member functions, no virtual base classes,
+ /// and no base class B for which is_empty<B>::value is false.
///
/// \note This does NOT include a check for union-ness.
bool isEmpty() const { return data().Empty; }
@@ -1270,6 +1276,14 @@ public:
return !(data().HasTrivialSpecialMembers & SMF_Destructor);
}
+ /// \brief Determine whether declaring a const variable with this type is ok
+ /// per core issue 253.
+ bool allowConstDefaultInit() const {
+ return !data().HasUninitializedFields ||
+ !(data().HasDefaultedDefaultConstructor ||
+ needsImplicitDefaultConstructor());
+ }
+
/// \brief Determine whether this class has a destructor which has no
/// semantic effect.
///
@@ -1285,6 +1299,18 @@ public:
return data().HasNonLiteralTypeFieldsOrBases;
}
+ /// \brief Determine whether this class has a using-declaration that names
+ /// a user-declared base class constructor.
+ bool hasInheritedConstructor() const {
+ return data().HasInheritedConstructor;
+ }
+
+ /// \brief Determine whether this class has a using-declaration that names
+ /// a base class assignment operator.
+ bool hasInheritedAssignment() const {
+ return data().HasInheritedAssignment;
+ }
+
/// \brief Determine whether this class is considered trivially copyable per
/// (C++11 [class]p6).
bool isTriviallyCopyable() const;
@@ -1555,6 +1581,14 @@ public:
CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
+ /// an OpenMP declare reduction member with the given name.
+ ///
+ /// This callback can be used with \c lookupInBases() to find members
+ /// of the given name within a C++ class hierarchy.
+ static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, DeclarationName Name);
+
+ /// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
/// This callback can be used with \c lookupInBases() to find members of
@@ -1690,6 +1724,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class ASTRecordWriter;
friend class ASTReader;
friend class ASTWriter;
};
@@ -1795,6 +1830,8 @@ public:
method_iterator begin_overridden_methods() const;
method_iterator end_overridden_methods() const;
unsigned size_overridden_methods() const;
+ typedef ASTContext::overridden_method_range overridden_method_range;
+ overridden_method_range overridden_methods() const;
/// Returns the parent of this method declaration, which
/// is the class in which this method is defined.
@@ -1910,15 +1947,15 @@ class CXXCtorInitializer final
/// \brief If the initializee is a type, whether that type makes this
/// a delegating initialization.
- bool IsDelegating : 1;
+ unsigned IsDelegating : 1;
/// \brief If the initializer is a base initializer, this keeps track
/// of whether the base is virtual or not.
- bool IsVirtual : 1;
+ unsigned IsVirtual : 1;
/// \brief Whether or not the initializer is explicitly written
/// in the sources.
- bool IsWritten : 1;
+ unsigned IsWritten : 1;
/// If IsWritten is true, then this number keeps track of the textual order
/// of this initializer in the original sources, counting from 0; otherwise,
@@ -2109,8 +2146,7 @@ public:
assert(I < getNumArrayIndices() && "Out of bounds member array index");
getTrailingObjects<VarDecl *>()[I] = Index;
}
- ArrayRef<VarDecl *> getArrayIndexes() {
- assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
+ ArrayRef<VarDecl *> getArrayIndices() {
return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
getNumArrayIndices());
}
@@ -2121,6 +2157,23 @@ public:
friend TrailingObjects;
};
+/// Description of a constructor that was inherited from a base class.
+class InheritedConstructor {
+ ConstructorUsingShadowDecl *Shadow;
+ CXXConstructorDecl *BaseCtor;
+
+public:
+ InheritedConstructor() : Shadow(), BaseCtor() {}
+ InheritedConstructor(ConstructorUsingShadowDecl *Shadow,
+ CXXConstructorDecl *BaseCtor)
+ : Shadow(Shadow), BaseCtor(BaseCtor) {}
+
+ explicit operator bool() const { return Shadow; }
+
+ ConstructorUsingShadowDecl *getShadowDecl() const { return Shadow; }
+ CXXConstructorDecl *getConstructor() const { return BaseCtor; }
+};
+
/// \brief Represents a C++ constructor within a class.
///
/// For example:
@@ -2131,40 +2184,51 @@ public:
/// explicit X(int); // represented by a CXXConstructorDecl.
/// };
/// \endcode
-class CXXConstructorDecl : public CXXMethodDecl {
+class CXXConstructorDecl final
+ : public CXXMethodDecl,
+ private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> {
void anchor() override;
- /// \brief Whether this constructor declaration has the \c explicit keyword
- /// specified.
- bool IsExplicitSpecified : 1;
/// \name Support for base and member initializers.
/// \{
/// \brief The arguments used to initialize the base or member.
LazyCXXCtorInitializersPtr CtorInitializers;
- unsigned NumCtorInitializers;
+ unsigned NumCtorInitializers : 30;
/// \}
+ /// \brief Whether this constructor declaration has the \c explicit keyword
+ /// specified.
+ unsigned IsExplicitSpecified : 1;
+
+ /// \brief Whether this constructor declaration is an implicitly-declared
+ /// inheriting constructor.
+ unsigned IsInheritingConstructor : 1;
+
CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
- bool isImplicitlyDeclared, bool isConstexpr)
+ bool isImplicitlyDeclared, bool isConstexpr,
+ InheritedConstructor Inherited)
: CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, SourceLocation()),
- IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr),
- NumCtorInitializers(0) {
+ CtorInitializers(nullptr), NumCtorInitializers(0),
+ IsExplicitSpecified(isExplicitSpecified),
+ IsInheritingConstructor((bool)Inherited) {
setImplicit(isImplicitlyDeclared);
+ if (Inherited)
+ *getTrailingObjects<InheritedConstructor>() = Inherited;
}
public:
- static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- bool isExplicit,
- bool isInline, bool isImplicitlyDeclared,
- bool isConstexpr);
+ static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ bool InheritsConstructor);
+ static CXXConstructorDecl *
+ Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit, bool isInline, bool isImplicitlyDeclared,
+ bool isConstexpr,
+ InheritedConstructor Inherited = InheritedConstructor());
/// \brief Determine whether this constructor declaration has the
/// \c explicit keyword specified.
@@ -2311,11 +2375,15 @@ public:
/// an object.
bool isSpecializationCopyingObject() const;
- /// \brief Get the constructor that this inheriting constructor is based on.
- const CXXConstructorDecl *getInheritedConstructor() const;
+ /// \brief Determine whether this is an implicit constructor synthesized to
+ /// model a call to a constructor inherited from a base class.
+ bool isInheritingConstructor() const { return IsInheritingConstructor; }
- /// \brief Set the constructor that this inheriting constructor is based on.
- void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
+ /// \brief Get the constructor that this inheriting constructor is based on.
+ InheritedConstructor getInheritedConstructor() const {
+ return IsInheritingConstructor ? *getTrailingObjects<InheritedConstructor>()
+ : InheritedConstructor();
+ }
CXXConstructorDecl *getCanonicalDecl() override {
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
@@ -2330,6 +2398,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// \brief Represents a C++ destructor within a class.
@@ -2774,18 +2843,6 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
NamedDecl *UsingOrNextShadow;
friend class UsingDecl;
- UsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc,
- UsingDecl *Using, NamedDecl *Target)
- : NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
- redeclarable_base(C), Underlying(Target),
- UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
- if (Target) {
- setDeclName(Target->getDeclName());
- IdentifierNamespace = Target->getIdentifierNamespace();
- }
- setImplicit();
- }
-
typedef Redeclarable<UsingShadowDecl> redeclarable_base;
UsingShadowDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
@@ -2797,11 +2854,16 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
return getMostRecentDecl();
}
+protected:
+ UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc,
+ UsingDecl *Using, NamedDecl *Target);
+ UsingShadowDecl(Kind K, ASTContext &C, EmptyShell);
+
public:
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target) {
- return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target);
+ return new (C, DC) UsingShadowDecl(UsingShadow, C, DC, Loc, Using, Target);
}
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2813,6 +2875,7 @@ public:
using redeclarable_base::redecls;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
UsingShadowDecl *getCanonicalDecl() override {
return getFirstDecl();
@@ -2843,7 +2906,125 @@ public:
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
- static bool classofKind(Kind K) { return K == Decl::UsingShadow; }
+ static bool classofKind(Kind K) {
+ return K == Decl::UsingShadow || K == Decl::ConstructorUsingShadow;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a shadow constructor declaration introduced into a
+/// class by a C++11 using-declaration that names a constructor.
+///
+/// For example:
+/// \code
+/// struct Base { Base(int); };
+/// struct Derived {
+/// using Base::Base; // creates a UsingDecl and a ConstructorUsingShadowDecl
+/// };
+/// \endcode
+class ConstructorUsingShadowDecl final : public UsingShadowDecl {
+ void anchor() override;
+
+ /// \brief If this constructor using declaration inherted the constructor
+ /// from an indirect base class, this is the ConstructorUsingShadowDecl
+ /// in the named direct base class from which the declaration was inherited.
+ ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl;
+
+ /// \brief If this constructor using declaration inherted the constructor
+ /// from an indirect base class, this is the ConstructorUsingShadowDecl
+ /// that will be used to construct the unique direct or virtual base class
+ /// that receives the constructor arguments.
+ ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl;
+
+ /// \brief \c true if the constructor ultimately named by this using shadow
+ /// declaration is within a virtual base class subobject of the class that
+ /// contains this declaration.
+ unsigned IsVirtual : 1;
+
+ ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc,
+ UsingDecl *Using, NamedDecl *Target,
+ bool TargetInVirtualBase)
+ : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, Using,
+ Target->getUnderlyingDecl()),
+ NominatedBaseClassShadowDecl(
+ dyn_cast<ConstructorUsingShadowDecl>(Target)),
+ ConstructedBaseClassShadowDecl(NominatedBaseClassShadowDecl),
+ IsVirtual(TargetInVirtualBase) {
+ // If we found a constructor for a non-virtual base class, but it chains to
+ // a constructor for a virtual base, we should directly call the virtual
+ // base constructor instead.
+ // FIXME: This logic belongs in Sema.
+ if (!TargetInVirtualBase && NominatedBaseClassShadowDecl &&
+ NominatedBaseClassShadowDecl->constructsVirtualBase()) {
+ ConstructedBaseClassShadowDecl =
+ NominatedBaseClassShadowDecl->ConstructedBaseClassShadowDecl;
+ IsVirtual = true;
+ }
+ }
+ ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty)
+ : UsingShadowDecl(ConstructorUsingShadow, C, Empty) {}
+
+public:
+ static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc,
+ UsingDecl *Using, NamedDecl *Target,
+ bool IsVirtual);
+ static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ /// Returns the parent of this using shadow declaration, which
+ /// is the class in which this is declared.
+ //@{
+ const CXXRecordDecl *getParent() const {
+ return cast<CXXRecordDecl>(getDeclContext());
+ }
+ CXXRecordDecl *getParent() {
+ return cast<CXXRecordDecl>(getDeclContext());
+ }
+ //@}
+
+ /// \brief Get the inheriting constructor declaration for the direct base
+ /// class from which this using shadow declaration was inherited, if there is
+ /// one. This can be different for each redeclaration of the same shadow decl.
+ ConstructorUsingShadowDecl *getNominatedBaseClassShadowDecl() const {
+ return NominatedBaseClassShadowDecl;
+ }
+
+ /// \brief Get the inheriting constructor declaration for the base class
+ /// for which we don't have an explicit initializer, if there is one.
+ ConstructorUsingShadowDecl *getConstructedBaseClassShadowDecl() const {
+ return ConstructedBaseClassShadowDecl;
+ }
+
+ /// \brief Get the base class that was named in the using declaration. This
+ /// can be different for each redeclaration of this same shadow decl.
+ CXXRecordDecl *getNominatedBaseClass() const;
+
+ /// \brief Get the base class whose constructor or constructor shadow
+ /// declaration is passed the constructor arguments.
+ CXXRecordDecl *getConstructedBaseClass() const {
+ return cast<CXXRecordDecl>((ConstructedBaseClassShadowDecl
+ ? ConstructedBaseClassShadowDecl
+ : getTargetDecl())
+ ->getDeclContext());
+ }
+
+ /// \brief Returns \c true if the constructed base class is a virtual base
+ /// class subobject of this declaration's class.
+ bool constructsVirtualBase() const {
+ return IsVirtual;
+ }
+
+ /// \brief Get the constructor or constructor template in the derived class
+ /// correspnding to this using shadow declaration, if it has been implicitly
+ /// declared already.
+ CXXConstructorDecl *getConstructor() const;
+ void setConstructor(NamedDecl *Ctor);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ConstructorUsingShadow; }
friend class ASTDeclReader;
friend class ASTDeclWriter;