summaryrefslogtreecommitdiffstats
path: root/lib/AST
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-07-22 23:36:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-07-22 23:36:59 +0000
commit1a9b9adf6ff83d48a797f20cc607be9c5eb154c6 (patch)
tree9d5024a4b7fb4cb223347d9c35fe3d5065885a63 /lib/AST
parent8747ea8f68604c5c2719f387628b4f76074f3a77 (diff)
P0217R3: Parsing support and framework for AST representation of C++1z
decomposition declarations. There are a couple of things in the wording that seem strange here: decomposition declarations are permitted at namespace scope (which we partially support here) and they are permitted as the declaration in a template (which we reject). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@276492 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTDumper.cpp7
-rw-r--r--lib/AST/DeclBase.cpp2
-rw-r--r--lib/AST/DeclCXX.cpp38
-rw-r--r--lib/AST/ItaniumMangle.cpp20
4 files changed, 65 insertions, 2 deletions
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 872ba356a9..1a4207f512 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -428,6 +428,7 @@ namespace {
void VisitFunctionDecl(const FunctionDecl *D);
void VisitFieldDecl(const FieldDecl *D);
void VisitVarDecl(const VarDecl *D);
+ void VisitDecompositionDecl(const DecompositionDecl *D);
void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
void VisitImportDecl(const ImportDecl *D);
void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
@@ -1217,6 +1218,12 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) {
}
}
+void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) {
+ VisitVarDecl(D);
+ for (auto *B : D->bindings())
+ dumpDecl(B);
+}
+
void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
dumpStmt(D->getAsmString());
}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index e07bf480ec..8918e18d43 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -598,6 +598,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case CXXConversion:
case EnumConstant:
case Var:
+ case Binding:
case ImplicitParam:
case ParmVar:
case ObjCMethod:
@@ -678,6 +679,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Captured:
case TranslationUnit:
case ExternCContext:
+ case Decomposition:
case UsingDirective:
case BuiltinTemplate:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index d069bfdc3d..7e6c725348 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -2306,6 +2306,44 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
nullptr, SourceLocation(), false);
}
+void BindingDecl::anchor() {}
+
+BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdLoc, IdentifierInfo *Id) {
+ return new (C, DC) BindingDecl(DC, IdLoc, Id);
+}
+
+BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
+}
+
+void DecompositionDecl::anchor() {}
+
+DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation LSquareLoc,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC,
+ ArrayRef<BindingDecl *> Bindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
+ return new (C, DC, Extra)
+ DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
+}
+
+DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ unsigned NumBindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
+ auto *Result = new (C, ID, Extra) DecompositionDecl(
+ C, nullptr, SourceLocation(), SourceLocation(), QualType(), nullptr, StorageClass(), None);
+ // Set up and clean out the bindings array.
+ Result->NumBindings = NumBindings;
+ auto *Trail = Result->getTrailingObjects<BindingDecl *>();
+ for (unsigned I = 0; I != NumBindings; ++I)
+ new (Trail + I) BindingDecl*(nullptr);
+ return Result;
+}
+
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 51de561d5f..5b278314ae 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -593,7 +593,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return false;
const VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD) {
+ if (VD && !isa<DecompositionDecl>(D)) {
// C variables are not mangled.
if (VD->isExternC())
return false;
@@ -1193,7 +1193,23 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// ::= <source-name>
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ const IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+ // We mangle decomposition declarations as the name of their first binding.
+ if (auto *DD = dyn_cast<DecompositionDecl>(ND)) {
+ auto B = DD->bindings();
+ if (B.begin() == B.end()) {
+ // FIXME: This is ill-formed but we accept it as an extension.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle global empty decomposition decl");
+ Diags.Report(DD->getLocation(), DiagID);
+ break;
+ }
+ II = (*B.begin())->getIdentifier();
+ }
+
+ if (II) {
// We must avoid conflicts between internally- and externally-
// linked variable and function declaration names in the same TU:
// void test() { extern void foo(); }