[cfe-commits] r83700 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp
John McCall
rjmccall at apple.com
Fri Oct 9 22:48:20 PDT 2009
Author: rjmccall
Date: Sat Oct 10 00:48:19 2009
New Revision: 83700
URL: http://llvm.org/viewvc/llvm-project?rev=83700&view=rev
Log:
Qualified lookup through using declarations. Diagnose a new type of ambiguity.
Split the various ambiguous result enumerators into their own enum. Tests
for most of C++ [namespace.qual].
Added:
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp
cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Oct 10 00:48:19 2009
@@ -1996,6 +1996,10 @@
def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">;
def err_ambiguous_reference : Error<"reference to %0 is ambiguous">;
def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">;
+def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a "
+ "declaration in a different namespace">;
+def note_hidden_tag : Note<"type declaration hidden">;
+def note_hiding_object : Note<"declaration hides type">;
// C++ operator overloading
def err_operator_overload_needs_class_or_enum : Error<
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Oct 10 00:48:19 2009
@@ -1074,6 +1074,13 @@
/// functions into an OverloadedFunctionDecl.
FoundOverloaded,
+ /// @brief Name lookup results in an ambiguity; use
+ /// getAmbiguityKind to figure out what kind of ambiguity
+ /// we have.
+ Ambiguous
+ };
+
+ enum AmbiguityKind {
/// Name lookup results in an ambiguity because multiple
/// entities that meet the lookup criteria were found in
/// subobjects of different types. For example:
@@ -1117,7 +1124,22 @@
/// @endcode
AmbiguousReference,
- FirstAmbiguous = AmbiguousBaseSubobjectTypes
+ /// Name lookup results in an ambiguity because an entity with a
+ /// tag name was hidden by an entity with an ordinary name from
+ /// a different context.
+ /// @code
+ /// namespace A { struct Foo {}; }
+ /// namespace B { void Foo(); }
+ /// namespace C {
+ /// using namespace A;
+ /// using namespace B;
+ /// }
+ /// void test() {
+ /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+ /// // different namespace
+ /// }
+ /// @endcode
+ AmbiguousTagHiding
};
typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
@@ -1132,7 +1154,7 @@
}
bool isAmbiguous() const {
- return getKind() >= FirstAmbiguous;
+ return getKind() == Ambiguous;
}
LookupKind getKind() const {
@@ -1140,6 +1162,11 @@
return Kind;
}
+ AmbiguityKind getAmbiguityKind() const {
+ assert(isAmbiguous());
+ return Ambiguity;
+ }
+
iterator begin() const { return Decls.begin(); }
iterator end() const { return Decls.end(); }
@@ -1158,6 +1185,25 @@
Kind = Found;
}
+ /// \brief Add all the declarations from another set of lookup
+ /// results.
+ void addAllDecls(const LookupResult &Other) {
+ Decls.append(Other.begin(), Other.end());
+ Kind = Found;
+ }
+
+ /// \brief Hides a set of declarations.
+ template <class NamedDeclSet> void hideDecls(const NamedDeclSet &Set) {
+ unsigned I = 0, N = Decls.size();
+ while (I < N) {
+ if (Set.count(Decls[I]))
+ Decls[I] = Decls[--N];
+ else
+ I++;
+ }
+ Decls.set_size(N);
+ }
+
/// \brief Resolves the kind of the lookup, possibly hiding decls.
///
/// This should be called in any environment where lookup might
@@ -1181,6 +1227,11 @@
return *Decls.begin();
}
+ /// \brief Asks if the result is a single tag decl.
+ bool isSingleTagDecl() const {
+ return getKind() == Found && isa<TagDecl>(getFoundDecl());
+ }
+
/// \brief Make these results show that the name was found in
/// base classes of different types.
///
@@ -1193,6 +1244,13 @@
/// The given paths object is copied and invalidated.
void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+ /// \brief Make these results show that the name was found in
+ /// different contexts and a tag decl was hidden by an ordinary
+ /// decl in a different context.
+ void setAmbiguousQualifiedTagHiding() {
+ setAmbiguous(AmbiguousTagHiding);
+ }
+
/// \brief Clears out any current state.
void clear() {
Kind = NotFound;
@@ -1204,6 +1262,11 @@
void print(llvm::raw_ostream &);
private:
+ void setAmbiguous(AmbiguityKind AK) {
+ Kind = Ambiguous;
+ Ambiguity = AK;
+ }
+
void addDeclsFromBasePaths(const CXXBasePaths &P);
// Sanity checks.
@@ -1211,14 +1274,17 @@
assert(Kind != NotFound || Decls.size() == 0);
assert(Kind != Found || Decls.size() == 1);
assert(Kind == NotFound || Kind == Found ||
- Kind == AmbiguousBaseSubobjects || Decls.size() > 1);
- assert((Paths != NULL) == (Kind == AmbiguousBaseSubobjectTypes ||
- Kind == AmbiguousBaseSubobjects));
+ (Kind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
+ || Decls.size() > 1);
+ assert((Paths != NULL) == (Kind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
}
static void deletePaths(CXXBasePaths *);
LookupKind Kind;
+ AmbiguityKind Ambiguity; // ill-defined unless ambiguous
DeclsTy Decls;
CXXBasePaths *Paths;
};
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Oct 10 00:48:19 2009
@@ -94,9 +94,15 @@
case LookupResult::FoundOverloaded:
return 0;
- case LookupResult::AmbiguousBaseSubobjectTypes:
- case LookupResult::AmbiguousBaseSubobjects:
- case LookupResult::AmbiguousReference: {
+ case LookupResult::Ambiguous: {
+ // Recover from type-hiding ambiguities by hiding the type. We'll
+ // do the lookup again when looking for an object, and we can
+ // diagnose the error then. If we don't do this, then the error
+ // about hiding the type will be immediately followed by an error
+ // that only makes sense if the identifier was treated like a type.
+ if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding)
+ return 0;
+
// Look to see if we have a type anywhere in the list of results.
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
Res != ResEnd; ++Res) {
@@ -4129,6 +4135,8 @@
bool isStdBadAlloc = false;
bool Invalid = false;
+ bool RedeclarationOnly = (TUK != TUK_Reference);
+
if (Name && SS.isNotEmpty()) {
// We have a nested-name tag ('struct foo::bar').
@@ -4155,11 +4163,18 @@
SearchDC = DC;
// Look-up name inside 'foo::'.
LookupResult R;
- LookupQualifiedName(R, DC, Name, LookupTagName, true);
- PrevDecl = dyn_cast_or_null<TagDecl>(R.getAsSingleDecl(Context));
+ LookupQualifiedName(R, DC, Name, LookupTagName, RedeclarationOnly);
+
+ if (R.isAmbiguous()) {
+ DiagnoseAmbiguousLookup(R, Name, NameLoc, SS.getRange());
+ return DeclPtrTy();
+ }
+
+ if (R.getKind() == LookupResult::Found)
+ PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl());
// A tag 'foo::bar' must already exist.
- if (PrevDecl == 0) {
+ if (!PrevDecl) {
Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
Name = 0;
Invalid = true;
@@ -4172,8 +4187,7 @@
// shouldn't be. Doing so can result in ambiguities that we
// shouldn't be diagnosing.
LookupResult R;
- LookupName(R, S, Name, LookupTagName,
- /*RedeclarationOnly=*/(TUK != TUK_Reference));
+ LookupName(R, S, Name, LookupTagName, RedeclarationOnly);
if (R.isAmbiguous()) {
DiagnoseAmbiguousLookup(R, Name, NameLoc);
// FIXME: This is not best way to recover from case like:
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Sat Oct 10 00:48:19 2009
@@ -25,6 +25,7 @@
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ErrorHandling.h"
#include <set>
#include <vector>
#include <iterator>
@@ -162,6 +163,9 @@
// Fast case: no possible ambiguity.
if (N <= 1) return;
+ // Don't do any extra resolution if we've already resolved as ambiguous.
+ if (Kind == Ambiguous) return;
+
llvm::SmallPtrSet<NamedDecl*, 16> Unique;
bool Ambiguous = false;
@@ -218,11 +222,11 @@
Ambiguous = true;
if (Ambiguous)
- Kind = AmbiguousReference;
+ setAmbiguous(LookupResult::AmbiguousReference);
else if (N > 1)
- Kind = FoundOverloaded;
+ Kind = LookupResult::FoundOverloaded;
else
- Kind = Found;
+ Kind = LookupResult::Found;
}
/// @brief Converts the result of name lookup into a single (possible
@@ -278,7 +282,7 @@
Paths->swap(P);
addDeclsFromBasePaths(*Paths);
resolveKind();
- Kind = AmbiguousBaseSubobjects;
+ setAmbiguous(AmbiguousBaseSubobjects);
}
void Sema::LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) {
@@ -286,7 +290,7 @@
Paths->swap(P);
addDeclsFromBasePaths(*Paths);
resolveKind();
- Kind = AmbiguousBaseSubobjectTypes;
+ setAmbiguous(AmbiguousBaseSubobjectTypes);
}
void Sema::LookupResult::print(llvm::raw_ostream &Out) {
@@ -644,6 +648,120 @@
return false;
}
+/// @brief Perform qualified name lookup in the namespaces nominated by
+/// using directives by the given context.
+///
+/// C++98 [namespace.qual]p2:
+/// Given X::m (where X is a user-declared namespace), or given ::m
+/// (where X is the global namespace), let S be the set of all
+/// declarations of m in X and in the transitive closure of all
+/// namespaces nominated by using-directives in X and its used
+/// namespaces, except that using-directives are ignored in any
+/// namespace, including X, directly containing one or more
+/// declarations of m. No namespace is searched more than once in
+/// the lookup of a name. If S is the empty set, the program is
+/// ill-formed. Otherwise, if S has exactly one member, or if the
+/// context of the reference is a using-declaration
+/// (namespace.udecl), S is the required set of declarations of
+/// m. Otherwise if the use of m is not one that allows a unique
+/// declaration to be chosen from S, the program is ill-formed.
+/// C++98 [namespace.qual]p5:
+/// During the lookup of a qualified namespace member name, if the
+/// lookup finds more than one declaration of the member, and if one
+/// declaration introduces a class name or enumeration name and the
+/// other declarations either introduce the same object, the same
+/// enumerator or a set of functions, the non-type name hides the
+/// class or enumeration name if and only if the declarations are
+/// from the same namespace; otherwise (the declarations are from
+/// different namespaces), the program is ill-formed.
+static bool LookupQualifiedNameInUsingDirectives(Sema::LookupResult &R,
+ DeclContext *StartDC,
+ DeclarationName Name,
+ Sema::LookupNameKind NameKind,
+ unsigned IDNS) {
+ assert(StartDC->isFileContext() && "start context is not a file context");
+
+ DeclContext::udir_iterator I = StartDC->using_directives_begin();
+ DeclContext::udir_iterator E = StartDC->using_directives_end();
+
+ if (I == E) return false;
+
+ // We have at least added all these contexts to the queue.
+ llvm::DenseSet<DeclContext*> Visited;
+ Visited.insert(StartDC);
+
+ // We have not yet looked into these namespaces, much less added
+ // their "using-children" to the queue.
+ llvm::SmallVector<NamespaceDecl*, 8> Queue;
+
+ // We have already looked into the initial namespace; seed the queue
+ // with its using-children.
+ for (; I != E; ++I) {
+ NamespaceDecl *ND = (*I)->getNominatedNamespace();
+ if (Visited.insert(ND).second)
+ Queue.push_back(ND);
+ }
+
+ // The easiest way to implement the restriction in [namespace.qual]p5
+ // is to check whether any of the individual results found a tag
+ // and, if so, to declare an ambiguity if the final result is not
+ // a tag.
+ bool FoundTag = false;
+ bool FoundNonTag = false;
+
+ Sema::LookupResult LocalR;
+
+ bool Found = false;
+ while (!Queue.empty()) {
+ NamespaceDecl *ND = Queue.back();
+ Queue.pop_back();
+
+ // We go through some convolutions here to avoid copying results
+ // between LookupResults.
+ bool UseLocal = !R.empty();
+ Sema::LookupResult &DirectR = UseLocal ? LocalR : R;
+ bool FoundDirect = LookupDirect(DirectR, ND, Name, NameKind, IDNS);
+
+ if (FoundDirect) {
+ // First do any local hiding.
+ DirectR.resolveKind();
+
+ // If the local result is a tag, remember that.
+ if (DirectR.isSingleTagDecl())
+ FoundTag = true;
+ else
+ FoundNonTag = true;
+
+ // Append the local results to the total results if necessary.
+ if (UseLocal) {
+ R.addAllDecls(LocalR);
+ LocalR.clear();
+ }
+ }
+
+ // If we find names in this namespace, ignore its using directives.
+ if (FoundDirect) {
+ Found = true;
+ continue;
+ }
+
+ for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) {
+ NamespaceDecl *Nom = (*I)->getNominatedNamespace();
+ if (Visited.insert(Nom).second)
+ Queue.push_back(Nom);
+ }
+ }
+
+ if (Found) {
+ if (FoundTag && FoundNonTag)
+ R.setAmbiguousQualifiedTagHiding();
+ else
+ R.resolveKind();
+ }
+
+ return Found;
+}
+
/// @brief Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
@@ -704,9 +822,26 @@
return true;
}
+ // Don't descend into implied contexts for redeclarations.
+ // C++98 [namespace.qual]p6:
+ // In a declaration for a namespace member in which the
+ // declarator-id is a qualified-id, given that the qualified-id
+ // for the namespace member has the form
+ // nested-name-specifier unqualified-id
+ // the unqualified-id shall name a member of the namespace
+ // designated by the nested-name-specifier.
+ // See also [class.mfct]p5 and [class.static.data]p2.
+ if (RedeclarationOnly)
+ return false;
+
+ // If this is a namespace, look it up in
+ if (LookupCtx->isFileContext())
+ return LookupQualifiedNameInUsingDirectives(R, LookupCtx, Name, NameKind,
+ IDNS);
+
// If this isn't a C++ class, we aren't allowed to look into base
// classes, we're done.
- if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
+ if (!isa<CXXRecordDecl>(LookupCtx))
return false;
// Perform lookup into our base classes.
@@ -895,31 +1030,32 @@
SourceRange LookupRange) {
assert(Result.isAmbiguous() && "Lookup result must be ambiguous");
- if (CXXBasePaths *Paths = Result.getBasePaths()) {
- if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) {
- QualType SubobjectType = Paths->front().back().Base->getType();
- Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
- << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
- << LookupRange;
-
- DeclContext::lookup_iterator Found = Paths->front().Decls.first;
- while (isa<CXXMethodDecl>(*Found) &&
- cast<CXXMethodDecl>(*Found)->isStatic())
- ++Found;
-
- Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
-
- return true;
- }
-
- assert(Result.getKind() == LookupResult::AmbiguousBaseSubobjectTypes &&
- "Unhandled form of name lookup ambiguity");
+ switch (Result.getAmbiguityKind()) {
+ case LookupResult::AmbiguousBaseSubobjects: {
+ CXXBasePaths *Paths = Result.getBasePaths();
+ QualType SubobjectType = Paths->front().back().Base->getType();
+ Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects)
+ << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
+ << LookupRange;
+
+ DeclContext::lookup_iterator Found = Paths->front().Decls.first;
+ while (isa<CXXMethodDecl>(*Found) &&
+ cast<CXXMethodDecl>(*Found)->isStatic())
+ ++Found;
+
+ Diag((*Found)->getLocation(), diag::note_ambiguous_member_found);
+
+ return true;
+ }
+ case LookupResult::AmbiguousBaseSubobjectTypes: {
Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types)
<< Name << LookupRange;
-
+
+ CXXBasePaths *Paths = Result.getBasePaths();
std::set<Decl *> DeclsPrinted;
- for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end();
+ for (CXXBasePaths::paths_iterator Path = Paths->begin(),
+ PathEnd = Paths->end();
Path != PathEnd; ++Path) {
Decl *D = *Path->Decls.first;
if (DeclsPrinted.insert(D).second)
@@ -929,15 +1065,40 @@
return true;
}
- assert(Result.getKind() == LookupResult::AmbiguousReference &&
- "unhandled form of name lookup ambiguity");
- Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
+ case LookupResult::AmbiguousTagHiding: {
+ Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange;
+ llvm::SmallPtrSet<NamedDecl*,8> TagDecls;
+
+ LookupResult::iterator DI, DE = Result.end();
+ for (DI = Result.begin(); DI != DE; ++DI)
+ if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) {
+ TagDecls.insert(TD);
+ Diag(TD->getLocation(), diag::note_hidden_tag);
+ }
+
+ for (DI = Result.begin(); DI != DE; ++DI)
+ if (!isa<TagDecl>(*DI))
+ Diag((*DI)->getLocation(), diag::note_hiding_object);
+
+ // For recovery purposes, go ahead and implement the hiding.
+ Result.hideDecls(TagDecls);
+
+ return true;
+ }
+
+ case LookupResult::AmbiguousReference: {
+ Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange;
- LookupResult::iterator DI = Result.begin(), DE = Result.end();
- for (; DI != DE; ++DI)
- Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+ LookupResult::iterator DI = Result.begin(), DE = Result.end();
+ for (; DI != DE; ++DI)
+ Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI;
+
+ return true;
+ }
+ }
+ llvm::llvm_unreachable("unknown ambiguity kind");
return true;
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Oct 10 00:48:19 2009
@@ -3858,9 +3858,7 @@
Referenced = *Result.begin();
break;
- case LookupResult::AmbiguousBaseSubobjectTypes:
- case LookupResult::AmbiguousBaseSubobjects:
- case LookupResult::AmbiguousReference:
+ case LookupResult::Ambiguous:
DiagnoseAmbiguousLookup(Result, Name, Range.getEnd(), Range);
return QualType();
}
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=83700&r1=83699&r2=83700&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Oct 10 00:48:19 2009
@@ -194,7 +194,13 @@
case DeclSpec::TST_union:
case DeclSpec::TST_struct: {
Decl *D = static_cast<Decl *>(DS.getTypeRep());
- assert(D && "Didn't get a decl for a class/enum/union/struct?");
+ if (!D) {
+ // This can happen in C++ with ambiguous lookups.
+ Result = Context.IntTy;
+ isInvalid = true;
+ break;
+ }
+
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp?rev=83700&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp Sat Oct 10 00:48:19 2009
@@ -0,0 +1,65 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace Ints {
+ int zero = 0; // expected-note {{candidate found by name lookup is 'Ints::zero'}}
+ void f(int); // expected-note 3 {{candidate function}}
+ void g(int);
+}
+
+namespace Floats {
+ float zero = 0.0f; // expected-note {{candidate found by name lookup is 'Floats::zero'}}
+ void f(float); // expected-note 3 {{candidate function}}
+ void g(float);
+}
+
+namespace Numbers {
+ using namespace Ints;
+ using namespace Floats;
+}
+
+void test() {
+ int i = Ints::zero;
+ Ints::f(i);
+
+ float f = Floats::zero;
+ Floats::f(f);
+
+ double n = Numbers::zero; // expected-error {{reference to 'zero' is ambiguous}}
+ Numbers::f(n); // expected-error{{call to 'f' is ambiguous}}
+ Numbers::f(i);
+ Numbers::f(f);
+}
+
+namespace Numbers {
+ struct Number {
+ explicit Number(double d) : d(d) {}
+ double d;
+ };
+ Number zero(0.0f);
+ void g(Number);
+}
+
+void test2() {
+ Numbers::Number n = Numbers::zero;
+ Numbers::f(n); // expected-error {{no matching function for call to 'f'}}
+ Numbers::g(n);
+}
+
+namespace Numbers2 {
+ using Numbers::f;
+ using Numbers::g;
+}
+
+void test3() {
+ Numbers::Number n = Numbers::zero;
+ Numbers2::f(n); // expected-error {{no matching function for call to 'f'}}
+ Numbers2::g(n);
+
+ int i = Ints::zero;
+ Numbers2::f(i);
+ Numbers2::g(i); // expected-error {{incompatible type passing 'int'}}
+
+ float f = Floats::zero;
+ Numbers2::f(f);
+ Numbers2::g(f); // expected-error {{incompatible type passing 'float'}}
+}
Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp?rev=83700&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp Sat Oct 10 00:48:19 2009
@@ -0,0 +1,41 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This is basically paraphrased from the standard.
+
+namespace Root {
+ int i = 0;
+ void f();
+}
+
+namespace A {
+ using namespace Root;
+}
+
+namespace B {
+ using namespace Root;
+}
+
+namespace AB {
+ using namespace A;
+ using namespace B;
+}
+
+void test() {
+ if (AB::i)
+ AB::f();
+}
+
+namespace C {
+ using Root::i;
+ using Root::f;
+}
+
+namespace AC {
+ using namespace A;
+ using namespace C;
+}
+
+void test2() {
+ if (AC::i)
+ AC::f();
+}
Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp?rev=83700&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp Sat Oct 10 00:48:19 2009
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ int a;
+}
+
+namespace C {
+ int c;
+}
+
+namespace B {
+ using namespace C;
+ int b;
+}
+
+namespace C {
+ using namespace B;
+ using namespace A;
+}
+
+void test() {
+ C::a++;
+ C::b++;
+ C::c++;
+}
Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp?rev=83700&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp Sat Oct 10 00:48:19 2009
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ struct x {}; // expected-note {{candidate found by name lookup is 'A::x'}}
+ int x; // expected-note {{candidate found by name lookup is 'A::x'}}
+
+ struct y {}; // expected-note {{type declaration hidden}}
+
+ struct z;
+ void z(float);
+}
+
+namespace B {
+ struct x {}; // expected-note {{candidate found by name lookup is 'B::x'}}
+ float x; // expected-note {{candidate found by name lookup is 'B::x'}}
+
+ float y; // expected-note {{declaration hides type}}
+
+ void z(int);
+}
+
+namespace AB {
+ using namespace A;
+ using namespace B;
+}
+
+void test() {
+ struct AB::x foo; // expected-error {{reference to 'x' is ambiguous}}
+ int i = AB::x; // expected-error {{reference to 'x' is ambiguous}}
+
+ struct AB::y bar;
+ float f = AB::y; // expected-error {{a type named 'y' is hidden by a declaration in a different namespace}}
+ AB::z(i);
+ AB::z(f);
+}
More information about the cfe-commits
mailing list