forked from OSchip/llvm-project
PR12710 - broken default argument handling for templates.
I broke this in r155838 by not actually instantiating non-dependent default arg expressions. The motivation for that change was to avoid producing duplicate conversion warnings for such default args (we produce them once when we parse the template - there's no need to produce them at each instantiation) but without actually instantiating the default arg, things break in weird ways. Technically, I think we could still get the right diagnostic experience without the bugs if we instantiated the non-dependent args (for non-dependent params only) immediately, rather than lazily. But I'm not sure if such a refactoring/ change would be desirable so here's the conservative fix for now. llvm-svn: 155893
This commit is contained in:
parent
124066c5cb
commit
7afed5e5bf
|
@ -1594,13 +1594,11 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
|
||||||
} else if (OldParm->hasUnparsedDefaultArg()) {
|
} else if (OldParm->hasUnparsedDefaultArg()) {
|
||||||
NewParm->setUnparsedDefaultArg();
|
NewParm->setUnparsedDefaultArg();
|
||||||
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
|
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
|
||||||
} else if (Expr *Arg = OldParm->getDefaultArg()) {
|
} else if (Expr *Arg = OldParm->getDefaultArg())
|
||||||
if (Arg->isInstantiationDependent() ||
|
// FIXME: if we non-lazily instantiated non-dependent default args for
|
||||||
OldDI->getType()->isInstantiationDependentType())
|
// non-dependent parameter types we could remove a bunch of duplicate
|
||||||
NewParm->setUninstantiatedDefaultArg(Arg);
|
// conversion warnings for such arguments.
|
||||||
else
|
NewParm->setUninstantiatedDefaultArg(Arg);
|
||||||
NewParm->setDefaultArg(Arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
|
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
|
||||||
|
|
||||||
|
|
|
@ -350,6 +350,22 @@ namespace test8 {
|
||||||
// CHECK: unreachable
|
// CHECK: unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PR12710
|
||||||
|
namespace test9 {
|
||||||
|
struct ArgType {
|
||||||
|
~ArgType();
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
void f1(const ArgType& = ArgType());
|
||||||
|
void f2();
|
||||||
|
void bar() {
|
||||||
|
f1<int>();
|
||||||
|
f2();
|
||||||
|
}
|
||||||
|
// CHECK: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* %ref.tmp)
|
||||||
|
// CHECK: call void @_ZN5test92f2Ev()
|
||||||
|
}
|
||||||
|
|
||||||
// Checks from test3:
|
// Checks from test3:
|
||||||
|
|
||||||
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
|
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::<anonymous namespace>::D"* %this) unnamed_addr
|
||||||
|
|
|
@ -83,8 +83,10 @@ void test3() {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test4 {
|
namespace test4 {
|
||||||
|
// FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once
|
||||||
|
// not once for the template + once for every instantiation
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void tmpl(char c = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}}
|
void tmpl(char c = NULL, // expected-warning 3 {{implicit conversion of NULL constant to 'char'}}
|
||||||
T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \
|
T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \
|
||||||
expected-warning {{implicit conversion of NULL constant to 'int'}}
|
expected-warning {{implicit conversion of NULL constant to 'int'}}
|
||||||
T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}}
|
T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}}
|
||||||
|
@ -95,8 +97,8 @@ namespace test4 {
|
||||||
}
|
}
|
||||||
|
|
||||||
void func() {
|
void func() {
|
||||||
tmpl<char>(); // expected-note {{in instantiation of default function argument expression for 'tmpl<char>' required here}}
|
tmpl<char>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<char>' required here}}
|
||||||
tmpl<int>(); // expected-note {{in instantiation of default function argument expression for 'tmpl<int>' required here}}
|
tmpl<int>(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl<int>' required here}}
|
||||||
tmpl2<int*>();
|
tmpl2<int*>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue