diff options
-rw-r--r-- | include/clang/AST/Decl.h | 16 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 2 | ||||
-rw-r--r-- | include/clang/Basic/DeclNodes.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 6 | ||||
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 4 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 11 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 1 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 28 | ||||
-rw-r--r-- | lib/Serialization/ASTCommon.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 | ||||
-rw-r--r-- | test/Parser/cxx0x-attributes.cpp | 3 | ||||
-rw-r--r-- | test/SemaCXX/cxx11-ast-print.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/RecursiveASTVisitor.h | 2 |
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())); }) |