[cfe-commits] r63939 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaDecl.cpp test/SemaCXX/nested-name-spec.cpp test/SemaCXX/qualified-id-lookup.cpp
Douglas Gregor
dgregor at apple.com
Fri Feb 6 09:46:57 PST 2009
Author: dgregor
Date: Fri Feb 6 11:46:57 2009
New Revision: 63939
URL: http://llvm.org/viewvc/llvm-project?rev=63939&view=rev
Log:
Diagnose attempts to define a namespace member out-of-line when no
matching member exists. Thanks to Piotr Rak for reporting the problem!
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/nested-name-spec.cpp
cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=63939&r1=63938&r2=63939&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Feb 6 11:46:57 2009
@@ -860,6 +860,8 @@
"expected a class or namespace")
DIAG(err_invalid_declarator_scope, ERROR,
"definition or redeclaration of %0 not in a namespace enclosing %1")
+DIAG(err_invalid_declarator_global_scope, ERROR,
+ "definition or redeclaration of %0 cannot name the global scope")
DIAG(err_invalid_declarator_in_function, ERROR,
"definition or redeclaration of %0 not allowed inside a function")
DIAG(err_not_tag_in_scope, ERROR,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=63939&r1=63938&r2=63939&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Feb 6 11:46:57 2009
@@ -1139,14 +1139,14 @@
return DeclarationName();
}
-/// isNearlyMatchingMemberFunction - Determine whether the C++ member
-/// functions Declaration and Definition are "nearly" matching. This
-/// heuristic is used to improve diagnostics in the case where an
-/// out-of-line member function definition doesn't match any
-/// declaration within the class.
-static bool isNearlyMatchingMemberFunction(ASTContext &Context,
- FunctionDecl *Declaration,
- FunctionDecl *Definition) {
+/// isNearlyMatchingFunction - Determine whether the C++ functions
+/// Declaration and Definition are "nearly" matching. This heuristic
+/// is used to improve diagnostics in the case where an out-of-line
+/// function definition doesn't match any declaration within
+/// the class or namespace.
+static bool isNearlyMatchingFunction(ASTContext &Context,
+ FunctionDecl *Declaration,
+ FunctionDecl *Definition) {
if (Declaration->param_size() != Definition->param_size())
return false;
for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) {
@@ -1219,17 +1219,21 @@
// In this case, PrevDecl will point to the overload set
// containing the two f's declared in X, but neither of them
// matches.
- if (!CurContext->Encloses(DC)) {
+
+ // First check whether we named the global scope.
+ if (isa<TranslationUnitDecl>(DC)) {
+ Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope)
+ << Name << D.getCXXScopeSpec().getRange();
+ } else if (!CurContext->Encloses(DC)) {
// The qualifying scope doesn't enclose the original declaration.
// Emit diagnostic based on current scope.
SourceLocation L = D.getIdentifierLoc();
SourceRange R = D.getCXXScopeSpec().getRange();
- if (isa<FunctionDecl>(CurContext)) {
+ if (isa<FunctionDecl>(CurContext))
Diag(L, diag::err_invalid_declarator_in_function) << Name << R;
- } else {
+ else
Diag(L, diag::err_invalid_declarator_scope)
- << Name << cast<NamedDecl>(DC)->getDeclName() << R;
- }
+ << Name << cast<NamedDecl>(DC) << R;
InvalidDecl = true;
}
}
@@ -1628,10 +1632,9 @@
// Merge the decl with the existing one if appropriate. Since C functions
// are in a flat namespace, make sure we consider decls in outer scopes.
+ bool Redeclaration = false;
if (PrevDecl &&
(!getLangOptions().CPlusPlus||isDeclInScope(PrevDecl, DC, S))) {
- bool Redeclaration = false;
-
// If C++, determine whether NewFD is an overload of PrevDecl or
// a declaration that requires merging. If it's an overload,
// there's no more work to do here; we'll just add the new
@@ -1664,40 +1667,46 @@
}
}
}
+ }
- if (!Redeclaration && D.getCXXScopeSpec().isSet()) {
- // The user tried to provide an out-of-line definition for a
- // member function, but there was no such member function
- // declared (C++ [class.mfct]p2). For example:
- //
- // class X {
- // void f() const;
- // };
- //
- // void X::f() { } // ill-formed
- //
- // Complain about this problem, and attempt to suggest close
- // matches (e.g., those that differ only in cv-qualifiers and
- // whether the parameter types are references).
- Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
- << cast<CXXRecordDecl>(DC)->getDeclName()
- << D.getCXXScopeSpec().getRange();
- InvalidDecl = true;
-
- LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName,
- true);
- assert(!Prev.isAmbiguous() &&
- "Cannot have an ambiguity in previous-declaration lookup");
- for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
- Func != FuncEnd; ++Func) {
- if (isa<CXXMethodDecl>(*Func) &&
- isNearlyMatchingMemberFunction(Context, cast<FunctionDecl>(*Func),
- NewFD))
- Diag((*Func)->getLocation(), diag::note_member_def_close_match);
- }
-
- PrevDecl = 0;
+ if (D.getCXXScopeSpec().isSet() &&
+ (!PrevDecl || !Redeclaration)) {
+ // The user tried to provide an out-of-line definition for a
+ // function that is a member of a class or namespace, but there
+ // was no such member function declared (C++ [class.mfct]p2,
+ // C++ [namespace.memdef]p2). For example:
+ //
+ // class X {
+ // void f() const;
+ // };
+ //
+ // void X::f() { } // ill-formed
+ //
+ // Complain about this problem, and attempt to suggest close
+ // matches (e.g., those that differ only in cv-qualifiers and
+ // whether the parameter types are references).
+ DeclarationName CtxName;
+ if (DC->isRecord())
+ CtxName = cast<RecordDecl>(DC)->getDeclName();
+ else if (DC->isNamespace())
+ CtxName = cast<NamespaceDecl>(DC)->getDeclName();
+ // FIXME: global scope
+ Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match)
+ << CtxName << D.getCXXScopeSpec().getRange();
+ InvalidDecl = true;
+
+ LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName,
+ true);
+ assert(!Prev.isAmbiguous() &&
+ "Cannot have an ambiguity in previous-declaration lookup");
+ for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+ Func != FuncEnd; ++Func) {
+ if (isa<FunctionDecl>(*Func) &&
+ isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
+ Diag((*Func)->getLocation(), diag::note_member_def_close_match);
}
+
+ PrevDecl = 0;
}
// Handle attributes. We need to have merged decls when handling attributes
Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=63939&r1=63938&r2=63939&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Fri Feb 6 11:46:57 2009
@@ -123,3 +123,28 @@
Operators::operator bool() {
return true;
}
+
+namespace A {
+ void g(int&); // expected-note{{member declaration nearly matches}}
+}
+
+void A::f() {} // expected-error{{out-of-line definition does not match any declaration in 'A'}}
+
+void A::g(const int&) { } // expected-error{{out-of-line definition does not match any declaration in 'A'}}
+
+struct Struct { };
+
+void Struct::f() { } // expected-error{{out-of-line definition does not match any declaration in 'Struct'}}
+
+void global_func(int);
+void global_func2(int);
+
+namespace N {
+ void ::global_func(int) { } // expected-error{{definition or redeclaration of 'global_func' cannot name the global scope}}
+
+ void f();
+ // FIXME: if we move this to a separate definition of N, things break!
+}
+void ::global_func2(int) { } // expected-error{{definition or redeclaration of 'global_func2' cannot name the global scope}}
+
+void N::f() { } // okay
Modified: cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp?rev=63939&r1=63938&r2=63939&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp (original)
+++ cfe/trunk/test/SemaCXX/qualified-id-lookup.cpp Fri Feb 6 11:46:57 2009
@@ -109,4 +109,3 @@
int Undef::f() {
return sizeof(Undef);
}
-
More information about the cfe-commits
mailing list