aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h16
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h2
-rw-r--r--include/clang/Basic/DeclNodes.td1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Sema/Sema.h6
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/AST/Decl.cpp11
-rw-r--r--lib/AST/DeclBase.cpp1
-rw-r--r--lib/AST/DeclPrinter.cpp6
-rw-r--r--lib/CodeGen/CGDecl.cpp1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp1
-rw-r--r--lib/Parse/Parser.cpp12
-rw-r--r--lib/Sema/SemaDeclCXX.cpp28
-rw-r--r--lib/Serialization/ASTCommon.cpp1
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp8
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp6
-rw-r--r--test/Parser/cxx0x-attributes.cpp3
-rw-r--r--test/SemaCXX/cxx11-ast-print.cpp2
-rw-r--r--tools/libclang/RecursiveASTVisitor.h2
19 files changed, 81 insertions, 32 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 010563fdd9..42e6ae0657 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -3297,7 +3297,21 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Import; }
};
-
+
+/// \brief Represents an empty-declaration.
+class EmptyDecl : public Decl {
+ virtual void anchor();
+ EmptyDecl(DeclContext *DC, SourceLocation L)
+ : Decl(Empty, DC, L) { }
+
+public:
+ static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L);
+ static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Empty; }
+};
/// Insertion operator for diagnostics. This allows sending NamedDecl's
/// into a diagnostic with <<.
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index faec5ebe09..4b5e19e733 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1257,6 +1257,8 @@ DEF_TRAVERSE_DECL(BlockDecl, {
return true;
})
+DEF_TRAVERSE_DECL(EmptyDecl, { })
+
DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
TRY_TO(TraverseStmt(D->getAsmString()));
})
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index 6f2bb35725..ac7ad6fc6a 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -74,4 +74,5 @@ def StaticAssert : Decl;
def Block : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;
def Import : Decl;
+def Empty : Decl;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e87cdd7673..13e52e0c6c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1916,8 +1916,6 @@ def warn_attribute_not_on_decl : Warning<
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
def err_base_specifier_attribute : Error<
"%0 attribute cannot be applied to a base specifier">;
-def err_attribute_declaration : Error<
- "%0 attribute cannot be used in an attribute declaration">;
// Availability attribute
def warn_availability_unknown_platform : Warning<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7101286a7b..669cf9e814 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1447,8 +1447,10 @@ public:
SourceLocation AsmLoc,
SourceLocation RParenLoc);
- /// \brief Handle a C++11 attribute-declaration.
- void ActOnAttributeDeclaration(AttributeList *AttrList);
+ /// \brief Handle a C++11 empty-declaration and attribute-declaration.
+ Decl *ActOnEmptyDeclaration(Scope *S,
+ AttributeList *AttrList,
+ SourceLocation SemiLoc);
/// \brief The parser has processed a module import declaration.
///
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index a672c7e149..93c5c073d5 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1031,7 +1031,9 @@ namespace clang {
/// function specialization. (Microsoft extension).
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
/// \brief An ImportDecl recording a module import.
- DECL_IMPORT
+ DECL_IMPORT,
+ /// \brief An EmptyDecl record.
+ DECL_EMPTY
};
/// \brief Record codes for each kind of statement or expression.
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 0dbb0d30aa..d2a9f84cd4 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3343,6 +3343,17 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation());
}
+void EmptyDecl::anchor() {}
+
+EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
+ return new (C) EmptyDecl(DC, L);
+}
+
+EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl));
+ return new (Mem) EmptyDecl(0, SourceLocation());
+}
+
//===----------------------------------------------------------------------===//
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index f675436fc5..cdf150595c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -558,6 +558,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCategory:
case ObjCCategoryImpl:
case Import:
+ case Empty:
// Never looked up by name.
return 0;
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index dce4f9af25..2be0b6c804 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -51,6 +51,7 @@ namespace {
void VisitEnumDecl(EnumDecl *D);
void VisitRecordDecl(RecordDecl *D);
void VisitEnumConstantDecl(EnumConstantDecl *D);
+ void VisitEmptyDecl(EmptyDecl *D);
void VisitFunctionDecl(FunctionDecl *D);
void VisitFriendDecl(FriendDecl *D);
void VisitFieldDecl(FieldDecl *D);
@@ -723,6 +724,11 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
Out << *D->getAliasedNamespace();
}
+void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
+ prettyPrintAttributes(D);
+ Out << ";\n";
+}
+
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
Out << "__module_private__ ";
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index a4d673b8c3..9c523149bd 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -83,6 +83,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
case Decl::Label: // __label__ x;
case Decl::Import:
+ case Decl::Empty:
// None of these decls require codegen support.
return;
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 60ec323203..6442f04070 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -2742,6 +2742,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::TypeAliasTemplate:
case Decl::NamespaceAlias:
case Decl::Block:
+ case Decl::Empty:
break;
case Decl::CXXConstructor:
// Skip function templates
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index d9772755bd..24849edd63 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -626,15 +626,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
return DeclGroupPtrTy();
case tok::semi:
// Either a C++11 empty-declaration or attribute-declaration.
- if (attrs.Range.isValid()) {
- // FIXME: Add an AST representation for this.
- Actions.ActOnAttributeDeclaration(attrs.getList());
- return DeclGroupPtrTy();
- }
-
+ SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(),
+ attrs.getList(),
+ Tok.getLocation());
ConsumeExtraSemi(OutsideFunction);
- // TODO: Invoke action for top-level semicolon.
- return DeclGroupPtrTy();
+ break;
case tok::r_brace:
Diag(Tok, diag::err_extraneous_closing_brace);
ConsumeBrace();
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 8198856547..ce526a9ed3 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -10085,23 +10085,17 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
return LinkageSpec;
}
-/// \brief Perform semantic checks on a C++11 attribute-declaration.
-void Sema::ActOnAttributeDeclaration(AttributeList *AttrList) {
- // FIXME: Build an AST node for an attribute declaration and return it.
-
- // Since we do not support any attributes which can be used in an attribute
- // declaration, just diagnose standard and unknown attributes appropriately.
- for (/**/; AttrList; AttrList = AttrList->getNext()) {
- if (AttrList->getKind() == AttributeList::IgnoredAttribute ||
- AttrList->isInvalid())
- continue;
-
- Diag(AttrList->getLoc(),
- AttrList->getKind() == AttributeList::UnknownAttribute
- ? diag::warn_unknown_attribute_ignored
- : diag::err_attribute_declaration)
- << AttrList->getName();
- }
+Decl *Sema::ActOnEmptyDeclaration(Scope *S,
+ AttributeList *AttrList,
+ SourceLocation SemiLoc) {
+ Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
+ // Attribute declarations appertain to empty declaration so we handle
+ // them here.
+ if (AttrList)
+ ProcessDeclAttributeList(S, ED, AttrList);
+
+ CurContext->addDecl(ED);
+ return ED;
}
/// \brief Perform semantic analysis for the variable declaration that
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index 9f1514bdff..3319cc3641 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -168,6 +168,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::TypeAliasTemplate:
case Decl::ObjCProtocol:
case Decl::ObjCInterface:
+ case Decl::Empty:
return true;
// Never redeclarable.
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index f4d03cf775..504c2e6588 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -265,6 +265,7 @@ namespace clang {
void VisitFriendTemplateDecl(FriendTemplateDecl *D);
void VisitStaticAssertDecl(StaticAssertDecl *D);
void VisitBlockDecl(BlockDecl *BD);
+ void VisitEmptyDecl(EmptyDecl *D);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
@@ -1526,6 +1527,10 @@ void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
D->RParenLoc = ReadSourceLocation(Record, Idx);
}
+void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
+ VisitDecl(D);
+}
+
std::pair<uint64_t, uint64_t>
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
uint64_t LexicalOffset = Record[Idx++];
@@ -2129,6 +2134,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// locations.
D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
break;
+ case DECL_EMPTY:
+ D = EmptyDecl::CreateDeserialized(Context, ID);
+ break;
}
assert(D && "Unknown declaration reading AST file");
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 3795e21bdf..6c63a149c2 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -102,6 +102,7 @@ namespace clang {
void VisitFriendTemplateDecl(FriendTemplateDecl *D);
void VisitStaticAssertDecl(StaticAssertDecl *D);
void VisitBlockDecl(BlockDecl *D);
+ void VisitEmptyDecl(EmptyDecl *D);
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
uint64_t VisibleOffset);
@@ -780,6 +781,11 @@ void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
Code = serialization::DECL_FILE_SCOPE_ASM;
}
+void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) {
+ VisitDecl(D);
+ Code = serialization::DECL_EMPTY;
+}
+
void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getBody());
diff --git a/test/Parser/cxx0x-attributes.cpp b/test/Parser/cxx0x-attributes.cpp
index 4e7ac16cc5..5e4e388a26 100644
--- a/test/Parser/cxx0x-attributes.cpp
+++ b/test/Parser/cxx0x-attributes.cpp
@@ -279,4 +279,5 @@ int v4[2][[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
int v5()[[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}
[[attribute_declaration]]; // expected-warning {{unknown attribute 'attribute_declaration' ignored}}
-[[noreturn]]; // expected-error {{'noreturn' attribute cannot be used in an attribute declaration}}
+[[noreturn]]; // expected-error {{'noreturn' attribute only applies to functions and methods}}
+[[carries_dependency]]; // expected-error {{'carries_dependency' attribute only applies to functions, methods, and parameters}}
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
index 66ff0f064a..8e9480476c 100644
--- a/test/SemaCXX/cxx11-ast-print.cpp
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -38,3 +38,5 @@ const char *p8 = 4.9_quux;
const char *p9 = 0x42e3F_fritz;
// CHECK: const char *p10 = 3.300e+15_fritz;
const char *p10 = 3.300e+15_fritz;
+// CHECK: ;
+;
diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h
index 35d59d02cd..9788c956da 100644
--- a/tools/libclang/RecursiveASTVisitor.h
+++ b/tools/libclang/RecursiveASTVisitor.h
@@ -1199,6 +1199,8 @@ DEF_TRAVERSE_DECL(BlockDecl, {
return true;
})
+DEF_TRAVERSE_DECL(EmptyDecl, { })
+
DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
TRY_TO(TraverseStmt(D->getAsmString()));
})