diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-31 00:36:36 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-31 00:36:36 +0000 |
commit | 4e4d57069cf9402728e05f7fc856295a86e4801f (patch) | |
tree | f0f87d6cdc817bc00271c364ce260cfd796f5771 | |
parent | 7a126a474fdde06382b315b4e3d8ef0a21d4dc31 (diff) |
Enable inline namespaces in the AST.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112564 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Decl.h | 29 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 21 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp | 13 |
5 files changed, 57 insertions, 12 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 3a93193211..4fdcf68151 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -219,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { + bool IsInline : 1; + SourceLocation LBracLoc, RBracLoc; // For extended namespace definitions: @@ -248,28 +250,33 @@ class NamespaceDecl : public NamedDecl, public DeclContext { NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - NextNamespace(0), OrigOrAnonNamespace(0, true) { } + IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); - // \brief Returns true if this is an anonymous namespace declaration. - // - // For example: + /// \brief Returns true if this is an anonymous namespace declaration. + /// + /// For example: /// \code - // namespace { - // ... - // }; - // \endcode - // q.v. C++ [namespace.unnamed] + /// namespace { + /// ... + /// }; + /// \endcode + /// q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } - /// \brief Returns true if this is a C++0x inline namespace. + /// \brief Returns true if this is an inline namespace declaration. bool isInline() const { - return false; + return IsInline; + } + + /// \brief Set whether this is an inline namespace declaration. + void setInline(bool Inline) { + IsInline = Inline; } /// \brief Return the next extended namespace declaration or null if there diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 32550dc616..d3fdb8050b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -421,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; def err_static_assert_failed : Error<"static_assert failed \"%0\"">; +def err_inline_namespace_mismatch : Error< + "%select{|non-}0inline namespace " + "cannot be reopened as %select{non-|}0inline">; + def err_unexpected_friend : Error< "friends can only be classes or functions">; def ext_enum_friend : ExtWarn< diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 0316124fbe..ca88377034 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -510,7 +510,7 @@ bool DeclContext::isTransparentContext() const { else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord) return cast<RecordDecl>(this)->isAnonymousStructOrUnion(); else if (DeclKind == Decl::Namespace) - return false; // FIXME: Check for C++0x inline namespaces + return cast<NamespaceDecl>(this)->isInline(); return false; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0ffc639816..008e384c58 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3289,6 +3289,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, (II ? IdentLoc : LBrace) , II); Namespc->setLBracLoc(LBrace); + Namespc->setInline(InlineLoc.isValid()); Scope *DeclRegionScope = NamespcScope->getParent(); @@ -3311,6 +3312,16 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { // This is an extended namespace definition. + if (Namespc->isInline() != OrigNS->isInline()) { + // inline-ness must match + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + Diag(OrigNS->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(OrigNS->isInline()); + } + // Attach this namespace decl to the chain of extended namespace // definitions. OrigNS->setNextNamespace(Namespc); @@ -3368,6 +3379,16 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, assert(!PrevDecl->getNextNamespace()); Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); PrevDecl->setNextNamespace(Namespc); + + if (Namespc->isInline() != PrevDecl->isInline()) { + // inline-ness must match + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(PrevDecl->isInline()); + } } CurContext->addDecl(Namespc); diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp new file mode 100644 index 0000000000..198b013518 --- /dev/null +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +namespace NIL {} // expected-note {{previous definition}} +inline namespace NIL {} // expected-error {{cannot be reopened as inline}} +inline namespace IL {} // expected-note {{previous definition}} +namespace IL {} // expected-error {{cannot be reopened as non-inline}} + +namespace {} // expected-note {{previous definition}} +inline namespace {} // expected-error {{cannot be reopened as inline}} +namespace X { + inline namespace {} // expected-note {{previous definition}} + namespace {} // expected-error {{cannot be reopened as non-inline}} +} |