Implement DR482: namespace members can be redeclared with a qualified name
within their namespace, and such a redeclaration isn't required to be a
definition any more.
Update DR status page to say Clang 3.4 instead of SVN and add new Clang 3.5
category (but keep Clang 3.4 yellow for now).
llvm-svn: 196481
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 17f19dc..451ebd2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4115,33 +4115,31 @@
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
- SourceLocation Loc) {
+ SourceLocation Loc) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
-
- // C++ [dcl.meaning]p1:
- // A declarator-id shall not be qualified except for the definition
- // of a member function (9.3) or static data member (9.4) outside of
- // its class, the definition or explicit instantiation of a function
- // or variable member of a namespace outside of its namespace, or the
- // definition of an explicit specialization outside of its namespace,
- // or the declaration of a friend function that is a member of
- // another class or namespace (11.3). [...]
-
- // The user provided a superfluous scope specifier that refers back to the
- // class or namespaces in which the entity is already declared.
+
+ // If the user provided a superfluous scope specifier that refers back to the
+ // class in which the entity is already declared, diagnose and ignore it.
//
// class X {
// void X::f();
// };
+ //
+ // Note, it was once ill-formed to give redundant qualification in all
+ // contexts, but that rule was removed by DR482.
if (Cur->Equals(DC)) {
- Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification
- : diag::err_member_extra_qualification)
- << Name << FixItHint::CreateRemoval(SS.getRange());
- SS.clear();
+ if (Cur->isRecord()) {
+ Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification
+ : diag::err_member_extra_qualification)
+ << Name << FixItHint::CreateRemoval(SS.getRange());
+ SS.clear();
+ } else {
+ Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name;
+ }
return false;
- }
+ }
// Check whether the qualifying scope encloses the scope of the original
// declaration.
@@ -7248,11 +7246,12 @@
}
}
- } else if (!D.isFunctionDefinition() && D.getCXXScopeSpec().isSet() &&
+ } else if (!D.isFunctionDefinition() &&
+ isa<CXXMethodDecl>(NewFD) && NewFD->isOutOfLine() &&
!isFriend && !isFunctionTemplateSpecialization &&
!isExplicitSpecialization) {
// An out-of-line member function declaration must also be a
- // definition (C++ [dcl.meaning]p1).
+ // definition (C++ [class.mfct]p2).
// Note that this is not the case for explicit specializations of
// function templates or member functions of class templates, per
// C++ [temp.expl.spec]p2. We also allow these declarations as an
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 0491267..162e46e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12133,11 +12133,13 @@
// If there is no declaration, there was an error parsing it.
if (D == 0 || D->isInvalidDecl()) return;
- // We should only get called for declarations with scope specifiers, like:
- // int foo::bar;
- assert(D->isOutOfLine());
- EnterDeclaratorContext(S, D->getDeclContext());
-
+ // We will always have a nested name specifier here, but this declaration
+ // might not be out of line if the specifier names the current namespace:
+ // extern int n;
+ // int ::n = 0;
+ if (D->isOutOfLine())
+ EnterDeclaratorContext(S, D->getDeclContext());
+
// If we are parsing the initializer for a static data member, push a
// new expression evaluation context that is associated with this static
// data member.
@@ -12152,10 +12154,10 @@
if (D == 0 || D->isInvalidDecl()) return;
if (isStaticDataMember(D))
- PopExpressionEvaluationContext();
+ PopExpressionEvaluationContext();
- assert(D->isOutOfLine());
- ExitDeclaratorContext(S);
+ if (D->isOutOfLine())
+ ExitDeclaratorContext(S);
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a