aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/DeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/DeclCXX.cpp')
-rw-r--r--lib/AST/DeclCXX.cpp122
1 files changed, 98 insertions, 24 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 51e8e14f804a..31ffeb0dcd1e 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -128,7 +128,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
bool DelayTypeCreation) {
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
PrevDecl);
- R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+ R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
// FIXME: DelayTypeCreation seems like such a hack
if (!DelayTypeCreation)
@@ -143,11 +143,11 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
LambdaCaptureDefault CaptureDefault) {
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
nullptr, nullptr);
- R->IsBeingDefined = true;
+ R->setBeingDefined(true);
R->DefinitionData =
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
CaptureDefault);
- R->MayHaveOutOfDateDef = false;
+ R->setMayHaveOutOfDateDef(false);
R->setImplicit(true);
C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
return R;
@@ -158,7 +158,7 @@ CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
auto *R = new (C, ID) CXXRecordDecl(
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
- R->MayHaveOutOfDateDef = false;
+ R->setMayHaveOutOfDateDef(false);
return R;
}
@@ -628,6 +628,24 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
return false;
}
+bool CXXRecordDecl::lambdaIsDefaultConstructibleAndAssignable() const {
+ assert(isLambda() && "not a lambda");
+
+ // C++2a [expr.prim.lambda.capture]p11:
+ // The closure type associated with a lambda-expression has no default
+ // constructor if the lambda-expression has a lambda-capture and a
+ // defaulted default constructor otherwise. It has a deleted copy
+ // assignment operator if the lambda-expression has a lambda-capture and
+ // defaulted copy and move assignment operators otherwise.
+ //
+ // C++17 [expr.prim.lambda]p21:
+ // The closure type associated with a lambda-expression has no default
+ // constructor and a deleted copy assignment operator.
+ if (getLambdaCaptureDefault() != LCD_None)
+ return false;
+ return getASTContext().getLangOpts().CPlusPlus2a;
+}
+
void CXXRecordDecl::addedMember(Decl *D) {
if (!D->isImplicit() &&
!isa<FieldDecl>(D) &&
@@ -731,9 +749,14 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
// C++11 [dcl.init.aggr]p1: DR1518
- // An aggregate is an array or a class with no user-provided, explicit, or
- // inherited constructors
- if (Constructor->isUserProvided() || Constructor->isExplicit())
+ // An aggregate is an array or a class with no user-provided [or]
+ // explicit [...] constructors
+ // C++20 [dcl.init.aggr]p1:
+ // An aggregate is an array or a class with no user-declared [...]
+ // constructors
+ if (getASTContext().getLangOpts().CPlusPlus2a
+ ? !Constructor->isImplicit()
+ : (Constructor->isUserProvided() || Constructor->isExplicit()))
data().Aggregate = false;
}
@@ -1327,6 +1350,15 @@ bool CXXRecordDecl::isGenericLambda() const {
return getLambdaData().IsGenericLambda;
}
+#ifndef NDEBUG
+static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
+ for (auto *D : R)
+ if (!declaresSameEntity(D, R.front()))
+ return false;
+ return true;
+}
+#endif
+
CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
if (!isLambda()) return nullptr;
DeclarationName Name =
@@ -1334,7 +1366,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
DeclContext::lookup_result Calls = lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
- assert(Calls.size() == 1 && "More than one lambda call operator!");
+ assert(allLookupResultsAreTheSame(Calls) &&
+ "More than one lambda call operator!");
NamedDecl *CallOp = Calls.front();
if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
@@ -1349,7 +1382,8 @@ CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
&getASTContext().Idents.get(getLambdaStaticInvokerName());
DeclContext::lookup_result Invoker = lookup(Name);
if (Invoker.empty()) return nullptr;
- assert(Invoker.size() == 1 && "More than one static invoker operator!");
+ assert(allLookupResultsAreTheSame(Invoker) &&
+ "More than one static invoker operator!");
NamedDecl *InvokerFun = Invoker.front();
if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());
@@ -1994,7 +2028,9 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
return nullptr;
}
-bool CXXMethodDecl::isUsualDeallocationFunction() const {
+bool CXXMethodDecl::isUsualDeallocationFunction(
+ SmallVectorImpl<const FunctionDecl *> &PreventedBy) const {
+ assert(PreventedBy.empty() && "PreventedBy is expected to be empty");
if (getOverloadedOperator() != OO_Delete &&
getOverloadedOperator() != OO_Array_Delete)
return false;
@@ -2052,14 +2088,16 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
- for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
- I != E; ++I) {
- if (const auto *FD = dyn_cast<FunctionDecl>(*I))
- if (FD->getNumParams() == 1)
- return false;
+ bool Result = true;
+ for (const auto *D : R) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getNumParams() == 1) {
+ PreventedBy.push_back(FD);
+ Result = false;
+ }
+ }
}
-
- return true;
+ return Result;
}
bool CXXMethodDecl::isCopyAssignmentOperator() const {
@@ -2135,19 +2173,24 @@ CXXMethodDecl::overridden_methods() const {
return getASTContext().overridden_methods(this);
}
-QualType CXXMethodDecl::getThisType(ASTContext &C) const {
+QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
+ const CXXRecordDecl *Decl) {
+ ASTContext &C = Decl->getASTContext();
+ QualType ClassTy = C.getTypeDeclType(Decl);
+ ClassTy = C.getQualifiedType(ClassTy, FPT->getTypeQuals());
+ return C.getPointerType(ClassTy);
+}
+
+QualType CXXMethodDecl::getThisType() const {
// C++ 9.3.2p1: The type of this in a member function of a class X is X*.
// If the member function is declared const, the type of this is const X*,
// if the member function is declared volatile, the type of this is
// volatile X*, and if the member function is declared const volatile,
// the type of this is const volatile X*.
-
assert(isInstance() && "No 'this' for static methods!");
- QualType ClassTy = C.getTypeDeclType(getParent());
- ClassTy = C.getQualifiedType(ClassTy,
- Qualifiers::fromCVRUMask(getTypeQualifiers()));
- return C.getPointerType(ClassTy);
+ return CXXMethodDecl::getThisType(getType()->getAs<FunctionProtoType>(),
+ getParent());
}
bool CXXMethodDecl::hasInlineBody() const {
@@ -2208,6 +2251,11 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
: Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}
+int64_t CXXCtorInitializer::getID(const ASTContext &Context) const {
+ return Context.getAllocator()
+ .identifyKnownAlignedObject<CXXCtorInitializer>(this);
+}
+
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
@@ -2246,6 +2294,21 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
return SourceRange(getSourceLocation(), getRParenLoc());
}
+CXXConstructorDecl::CXXConstructorDecl(
+ ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared,
+ bool isConstexpr, InheritedConstructor Inherited)
+ : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC_None, isInline, isConstexpr, SourceLocation()) {
+ setNumCtorInitializers(0);
+ setInheritingConstructor(static_cast<bool>(Inherited));
+ setImplicit(isImplicitlyDeclared);
+ if (Inherited)
+ *getTrailingObjects<InheritedConstructor>() = Inherited;
+ setExplicitSpecified(isExplicitSpecified);
+}
+
void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
@@ -2255,7 +2318,7 @@ CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
false, false, false, false, InheritedConstructor());
- Result->IsInheritingConstructor = Inherited;
+ Result->setInheritingConstructor(Inherited);
return Result;
}
@@ -2451,6 +2514,15 @@ bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
getConversionType()->isBlockPointerType();
}
+LinkageSpecDecl::LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
+ SourceLocation LangLoc, LanguageIDs lang,
+ bool HasBraces)
+ : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
+ ExternLoc(ExternLoc), RBraceLoc(SourceLocation()) {
+ setLanguage(lang);
+ LinkageSpecDeclBits.HasBraces = HasBraces;
+}
+
void LinkageSpecDecl::anchor() {}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
@@ -2838,6 +2910,8 @@ void DecompositionDecl::printName(llvm::raw_ostream &os) const {
os << ']';
}
+void MSPropertyDecl::anchor() {}
+
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,