Skip to content
Permalink
Browse files

Implement Herb Sutter's P0934 "A Modest Proposal: Fixing ADL."

  • Loading branch information...
Quuxplusone committed Aug 12, 2018
1 parent eda3b82 commit 9ff89141fedd36af27820f5cc3a0edd8a1bef2db
@@ -20,6 +20,7 @@ def Implicit : DiagGroup<"implicit", [
def : DiagGroup<"abi">;
def AbsoluteValue : DiagGroup<"absolute-value">;
def AddressOfTemporary : DiagGroup<"address-of-temporary">;
def ADL : DiagGroup<"adl">;
def : DiagGroup<"aggregate-return">;
def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
@@ -766,6 +767,7 @@ def Extra : DiagGroup<"extra", [
]>;

def Most : DiagGroup<"most", [
ADL,
CharSubscript,
Comment,
DeleteNonVirtualDtor,
@@ -3558,6 +3558,10 @@ def note_ovl_too_many_candidates : Note<
"remaining %0 candidate%s0 omitted; "
"pass -fshow-overloads=all to show them">;

def warn_ovl_from_template_parameter_adl : Warning<
"function '%0' was found via argument-dependent lookup "
"from a template type argument">, InGroup<ADL>, DefaultIgnore;

def select_ovl_candidate_kind : TextSubstitution<
"%select{function|function|constructor|"
"constructor (the implicit default constructor)|"
@@ -757,6 +757,10 @@ class Sema;
/// Viable - True to indicate that this overload candidate is viable.
bool Viable;

/// IsFromTemplateArgADL - True if this candidate would be
/// eliminated by P0934.
bool IsFromTemplateArgADL;

/// IsSurrogate - True to indicate that this candidate is a
/// surrogate for a conversion to a function pointer or reference
/// (C++ [over.call.object]).
@@ -2722,6 +2722,23 @@ class Sema {
bool PartialOverloading = false,
bool AllowExplicit = false,
ConversionSequenceList EarlyConversions = None);
void AddOverloadCandidateFromTemplateArgADL(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false,
bool AllowExplicit = false,
ConversionSequenceList EarlyConversions = None);
void AddOverloadCandidateImpl(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
bool AllowExplicit,
ConversionSequenceList EarlyConversions,
bool IsFromTemplateArgADL);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
@@ -2761,6 +2778,22 @@ class Sema {
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false);
void AddTemplateOverloadCandidateFromTemplateArgADL(
FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool PartialOverloading = false);
void AddTemplateOverloadCandidateImpl(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
bool IsFromTemplateArgADL);
bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate,
ArrayRef<QualType> ParamTypes,
ArrayRef<Expr *> Args,
@@ -3217,7 +3250,8 @@ class Sema {
bool isKnownName(StringRef name);

void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
ArrayRef<Expr *> Args, ADLResult &Functions);
ArrayRef<Expr *> Args, ADLResult &Functions,
bool IncludeTemplateArgs);

void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
@@ -3306,7 +3340,8 @@ class Sema {
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
ArrayRef<Expr *> Args,
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses);
AssociatedClassSet &AssociatedClasses,
bool IncludeTemplateArgs);

void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
bool ConsiderLinkage, bool AllowInlineNamespace);
@@ -2434,7 +2434,7 @@ namespace {
} // end anonymous namespace

static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T);
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T, bool IncludeTemplateArgs);

static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
DeclContext *Ctx) {
@@ -2458,7 +2458,8 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
const TemplateArgument &Arg) {
const TemplateArgument &Arg,
bool IncludeTemplateArgs) {
// C++ [basic.lookup.koenig]p2, last bullet:
// -- [...] ;
switch (Arg.getKind()) {
@@ -2469,7 +2470,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// [...] the namespaces and classes associated with the types of the
// template arguments provided for template type parameters (excluding
// template template parameters)
addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
addAssociatedClassesAndNamespaces(Result, Arg.getAsType(), IncludeTemplateArgs);
break;

case TemplateArgument::Template:
@@ -2499,7 +2500,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,

case TemplateArgument::Pack:
for (const auto &P : Arg.pack_elements())
addAssociatedClassesAndNamespaces(Result, P);
addAssociatedClassesAndNamespaces(Result, P, IncludeTemplateArgs);
break;
}
}
@@ -2509,7 +2510,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
CXXRecordDecl *Class) {
CXXRecordDecl *Class,
bool IncludeTemplateArgs) {

// Just silently ignore anything whose name is __va_list_tag.
if (Class->getDeclName() == Result.S.VAListTagName)
@@ -2556,9 +2558,11 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// Add the associated namespace for this class.
CollectEnclosingNamespace(Result.Namespaces, Ctx);

const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]);
if (IncludeTemplateArgs) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
addAssociatedClassesAndNamespaces(Result, TemplateArgs[I], IncludeTemplateArgs);
}
}

// Only recurse into base classes for complete types.
@@ -2603,7 +2607,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
// argument-dependent lookup with an argument of type T
// (C++ [basic.lookup.koenig]p2).
static void
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty,
bool IncludeTemplateArgs) {
// C++ [basic.lookup.koenig]p2:
//
// For each argument type T in the function call, there is a set
@@ -2658,7 +2663,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
case Type::Record: {
CXXRecordDecl *Class =
cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl());
addAssociatedClassesAndNamespaces(Result, Class);
addAssociatedClassesAndNamespaces(Result, Class, IncludeTemplateArgs);
break;
}

@@ -2773,7 +2778,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
void Sema::FindAssociatedClassesAndNamespaces(
SourceLocation InstantiationLoc, ArrayRef<Expr *> Args,
AssociatedNamespaceSet &AssociatedNamespaces,
AssociatedClassSet &AssociatedClasses) {
AssociatedClassSet &AssociatedClasses,
bool IncludeTemplateArgs) {
AssociatedNamespaces.clear();
AssociatedClasses.clear();

@@ -2791,7 +2797,7 @@ void Sema::FindAssociatedClassesAndNamespaces(
Expr *Arg = Args[ArgIdx];

if (Arg->getType() != Context.OverloadTy) {
addAssociatedClassesAndNamespaces(Result, Arg->getType());
addAssociatedClassesAndNamespaces(Result, Arg->getType(), IncludeTemplateArgs);
continue;
}

@@ -2816,7 +2822,7 @@ void Sema::FindAssociatedClassesAndNamespaces(

// Add the classes and namespaces associated with the parameter
// types and return type of this function.
addAssociatedClassesAndNamespaces(Result, FDecl->getType());
addAssociatedClassesAndNamespaces(Result, FDecl->getType(), IncludeTemplateArgs);
}
}
}
@@ -3304,14 +3310,16 @@ void ADLResult::insert(NamedDecl *New) {
}

void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
ArrayRef<Expr *> Args, ADLResult &Result) {
ArrayRef<Expr *> Args, ADLResult &Result,
bool IncludeTemplateArgs) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
AssociatedClassSet AssociatedClasses;
FindAssociatedClassesAndNamespaces(Loc, Args,
AssociatedNamespaces,
AssociatedClasses);
AssociatedClasses,
IncludeTemplateArgs);

// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
Oops, something went wrong.

0 comments on commit 9ff8914

Please sign in to comment.
You can’t perform that action at this time.