namespace.
llvm-svn: 166194
/// call.
bool RequiresADL;
- /// True if namespace ::std should be considered an associated namespace
- /// for the purposes of argument-dependent lookup. See C++0x [stmt.ranged]p1.
- bool StdIsAssociatedNamespace;
-
/// True if these lookup results are overloaded. This is pretty
/// trivially rederivable if we urgently need to kill this field.
bool Overloaded;
const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded,
const TemplateArgumentListInfo *TemplateArgs,
- UnresolvedSetIterator Begin, UnresolvedSetIterator End,
- bool StdIsAssociatedNamespace)
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End)
: OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc,
NameInfo, TemplateArgs, Begin, End, false, false, false),
RequiresADL(RequiresADL),
- StdIsAssociatedNamespace(StdIsAssociatedNamespace),
Overloaded(Overloaded), NamingClass(NamingClass)
{}
UnresolvedLookupExpr(EmptyShell Empty)
: OverloadExpr(UnresolvedLookupExprClass, Empty),
- RequiresADL(false), StdIsAssociatedNamespace(false), Overloaded(false),
- NamingClass(0)
+ RequiresADL(false), Overloaded(false), NamingClass(0)
{}
friend class ASTStmtReader;
const DeclarationNameInfo &NameInfo,
bool ADL, bool Overloaded,
UnresolvedSetIterator Begin,
- UnresolvedSetIterator End,
- bool StdIsAssociatedNamespace = false) {
- assert((ADL || !StdIsAssociatedNamespace) &&
- "std considered associated namespace when not performing ADL");
+ UnresolvedSetIterator End) {
return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
SourceLocation(), NameInfo,
- ADL, Overloaded, 0, Begin, End,
- StdIsAssociatedNamespace);
+ ADL, Overloaded, 0, Begin, End);
}
static UnresolvedLookupExpr *Create(ASTContext &C,
/// argument-dependent lookup.
bool requiresADL() const { return RequiresADL; }
- /// True if namespace \::std should be artificially added to the set of
- /// associated namespaces for argument-dependent lookup purposes.
- bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; }
-
/// True if this lookup is overloaded.
bool isOverloaded() const { return Overloaded; }
llvm::ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
- bool PartialOverloading = false,
- bool StdNamespaceIsAssociated = false);
+ bool PartialOverloading = false);
// Emit as a 'note' the specific overload candidate
void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType());
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
SourceLocation Loc,
llvm::ArrayRef<Expr *> Args,
- ADLResult &Functions,
- bool StdNamespaceIsAssociated = false);
+ ADLResult &Functions);
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo,
ADL, /*Overload*/ true, Args,
- Begin, End, /*StdIsAssociated=*/false);
+ Begin, End);
}
UnresolvedLookupExpr *
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
SourceLocation Loc,
llvm::ArrayRef<Expr *> Args,
- ADLResult &Result,
- bool StdNamespaceIsAssociated) {
+ ADLResult &Result) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
FindAssociatedClassesAndNamespaces(Loc, Args,
AssociatedNamespaces,
AssociatedClasses);
- if (StdNamespaceIsAssociated && StdNamespace)
- AssociatedNamespaces.insert(getStdNamespace());
QualType T1, T2;
if (Operator) {
llvm::ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
- bool PartialOverloading,
- bool StdNamespaceIsAssociated) {
+ bool PartialOverloading) {
ADLResult Fns;
// FIXME: This approach for uniquing ADL results (and removing
// we supposed to consider on ADL candidates, anyway?
// FIXME: Pass in the explicit template arguments?
- ArgumentDependentLookup(Name, Operator, Loc, Args, Fns,
- StdNamespaceIsAssociated);
+ ArgumentDependentLookup(Name, Operator, Loc, Args, Fns);
// Erase all of the candidates we already knew about.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
ULE->getExprLoc(),
Args, ExplicitTemplateArgs,
- CandidateSet, PartialOverloading,
- ULE->isStdAssociatedNamespace());
+ CandidateSet, PartialOverloading);
}
/// Attempt to recover from an ill-formed use of a non-dependent name in a
// We don't perform ADL in C.
assert(getLangOpts().CPlusPlus && "ADL enabled in C");
- } else
- assert(!ULE->isStdAssociatedNamespace() &&
- "std is associated namespace but not doing ADL");
+ }
#endif
UnbridgedCastsSet UnbridgedCasts;
}
} else {
UnresolvedSet<0> FoundNames;
- // C++11 [stmt.ranged]p1: For the purposes of this name lookup, namespace
- // std is an associated namespace.
UnresolvedLookupExpr *Fn =
UnresolvedLookupExpr::Create(Context, /*NamingClass=*/0,
NestedNameSpecifierLoc(), NameInfo,
/*NeedsADL=*/true, /*Overloaded=*/false,
- FoundNames.begin(), FoundNames.end(),
- /*LookInStdNamespace=*/true);
+ FoundNames.begin(), FoundNames.end());
bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, &Range, 1, Loc,
CandidateSet, CallExpr);
void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
E->RequiresADL = Record[Idx++];
- if (E->RequiresADL)
- E->StdIsAssociatedNamespace = Record[Idx++];
E->Overloaded = Record[Idx++];
E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx);
}
void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
Record.push_back(E->requiresADL());
- if (E->requiresADL())
- Record.push_back(E->isStdAssociatedNamespace());
Record.push_back(E->isOverloaded());
Writer.AddDeclRef(E->getNamingClass(), Record);
Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
}
};
-namespace std {
+struct null_t {
+ operator int*();
+};
+
+namespace X {
template<typename T>
- auto begin(T &&t) -> decltype(t.begin()) { return t.begin(); } // expected-note 4{{ignored: substitution failure}}
+ auto begin(T &&t) -> decltype(t.begin()) { return t.begin(); } // expected-note 2{{ignored: substitution failure}}
template<typename T>
auto end(T &&t) -> decltype(t.end()) { return t.end(); } // expected-note {{candidate template ignored: substitution failure [with T = }}
template<typename T>
auto begin(T &&t) -> decltype(t.alt_begin()) { return t.alt_begin(); } // expected-note {{selected 'begin' template [with T = }} \
- expected-note 4{{candidate template ignored: substitution failure [with T = }}
+ expected-note 2{{candidate template ignored: substitution failure [with T = }}
template<typename T>
auto end(T &&t) -> decltype(t.alt_end()) { return t.alt_end(); } // expected-note {{candidate template ignored: substitution failure [with T = }}
}
using namespace inner;
-}
-struct A { // expected-note 2 {{candidate constructor}}
- A();
- int *begin(); // expected-note 3{{selected 'begin' function with iterator type 'int *'}} expected-note {{'begin' declared here}}
- int *end();
-};
+ struct A { // expected-note 2 {{candidate constructor}}
+ A();
+ int *begin(); // expected-note 3{{selected 'begin' function with iterator type 'int *'}} expected-note {{'begin' declared here}}
+ int *end();
+ };
-struct B {
- B();
- int *alt_begin();
- int *alt_end();
-};
+ struct B {
+ B();
+ int *alt_begin();
+ int *alt_end();
+ };
+
+ struct NoBeginADL {
+ null_t alt_end();
+ };
+ struct NoEndADL {
+ null_t alt_begin();
+ };
+}
+
+using X::A;
void f();
void f(int);
A __begin;
for (char *a : A()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}}
}
- for (char *a : B()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}}
+ for (char *a : X::B()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}}
}
// FIXME: Terrible diagnostic here. auto deduction should fail, but does not!
for (double a : f) { // expected-error {{cannot use type '<overloaded function type>' as a range}}
}
for (auto a : A()) {
}
- for (auto a : B()) {
+ for (auto a : X::B()) {
}
for (auto *a : A()) { // expected-error {{variable 'a' with type 'auto *' has incompatible initializer of type 'int'}}
}
// : is not a typo for :: here.
- for (A NS:A()) { // expected-error {{no viable conversion from 'int' to 'A'}}
+ for (A NS:A()) { // expected-error {{no viable conversion from 'int' to 'X::A'}}
}
for (auto not_in_scope : not_in_scope) { // expected-error {{use of undeclared identifier 'not_in_scope'}}
}
for (auto a : VoidBegin()) // expected-error {{cannot use type 'void' as an iterator}}
;
- struct null_t {
- operator int*();
- };
struct Differ {
int *begin(); // expected-note {{selected 'begin' function with iterator type 'int *'}}
null_t end(); // expected-note {{selected 'end' function with iterator type 'null_t'}}
for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}}
for (constexpr int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'constexpr'}}
- struct NoBeginADL {
- null_t alt_end();
- };
- struct NoEndADL {
- null_t alt_begin();
- };
- for (auto u : NoBeginADL()) { // expected-error {{invalid range expression of type 'NoBeginADL'; no viable 'begin' function available}}
+ for (auto u : X::NoBeginADL()) { // expected-error {{invalid range expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
}
- for (auto u : NoEndADL()) { // expected-error {{invalid range expression of type 'NoEndADL'; no viable 'end' function available}}
+ for (auto u : X::NoEndADL()) { // expected-error {{invalid range expression of type 'X::NoEndADL'; no viable 'end' function available}}
}
struct NoBegin {
template<typename T, typename U>
void h(T t) {
- for (U u : t) { // expected-error {{no viable conversion from 'A' to 'int'}}
+ for (U u : t) { // expected-error {{no viable conversion from 'X::A' to 'int'}}
}
for (auto u : t) {
}
template<typename T>
void i(T t) {
- for (auto u : t) { // expected-error {{invalid range expression of type 'A *'; no viable 'begin' function available}} \
+ for (auto u : t) { // expected-error {{invalid range expression of type 'X::A *'; no viable 'begin' function available}} \
expected-error {{member function 'begin' not viable}} \
expected-note {{when looking up 'begin' function}}
template void i<A[13]>(A*); // expected-note {{requested here}}
template void i<const A>(const A); // expected-note {{requested here}}
+struct StdBeginEnd {};
+namespace std {
+ int *begin(StdBeginEnd);
+ int *end(StdBeginEnd);
+}
+void DR1442() {
+ for (auto a : StdBeginEnd()) {} // expected-error {{invalid range expression of type 'StdBeginEnd'; no viable 'begin'}}
+}
+
namespace NS {
class ADL {};
int *begin(ADL); // expected-note {{no known conversion from 'NS::NoADL' to 'NS::ADL'}}
B *end();
};
-namespace std {
- B *begin(C&);
- B *end(C&);
-}
+B *begin(C&);
+B *end(C&);
extern B array[5];
A a;
for (B b : C()) {
// CHECK: call void @_ZN1CC1Ev(
- // CHECK: = call %struct.B* @_ZSt5beginR1C(
- // CHECK: = call %struct.B* @_ZSt3endR1C(
+ // CHECK: = call %struct.B* @_Z5beginR1C(
+ // CHECK: = call %struct.B* @_Z3endR1C(
// CHECK: br label %[[COND:.*]]
// CHECK: [[COND]]:
char *begin(T);
char *end(T);
-struct U { };
-namespace std {
+namespace NS {
+ struct U { };
char *begin(U);
char *end(U);
}
+using NS::U;
void f() {
char a[3] = { 0, 1, 2 };