Ensure that default arguments are handled correctly in sub scopes. For example:

void f () {
  int g (int a, int b=4);
  {
    int g(int a, int b=5);
  }
}

should compile.

llvm-svn: 152621
This commit is contained in:
James Molloy
2012-03-13 08:55:35 +00:00
parent 5262ad2afa
commit e943003c09
5 changed files with 55 additions and 14 deletions

View File

@@ -1392,13 +1392,14 @@ public:
bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
void mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation = true);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
Scope *S);
void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
// AssignmentAction - This is used by all the assignment diagnostic functions
// to represent what is actually causing the operation

View File

@@ -1720,7 +1720,7 @@ static bool canRedefineFunction(const FunctionDecl *FD,
/// merged with.
///
/// Returns true if there was an error, false otherwise.
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) {
// Verify the old decl was also a function.
FunctionDecl *Old = 0;
if (FunctionTemplateDecl *OldFunctionTemplate
@@ -1950,7 +1950,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
}
if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old);
return MergeCompatibleFunctionDecls(New, Old, S);
// Fall through for conflicting redeclarations and redefinitions.
}
@@ -1995,7 +1995,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
New->setParams(Params);
}
return MergeCompatibleFunctionDecls(New, Old);
return MergeCompatibleFunctionDecls(New, Old, S);
}
// GNU C permits a K&R definition to follow a prototype declaration
@@ -2056,7 +2056,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
ArgTypes.size(),
OldProto->getExtProtoInfo()));
return MergeCompatibleFunctionDecls(New, Old);
return MergeCompatibleFunctionDecls(New, Old, S);
}
// Fall through to diagnose conflicting types.
@@ -2097,7 +2097,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
/// redeclaration of Old.
///
/// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
Scope *S) {
// Merge the attributes
mergeDeclAttributes(New, Old);
@@ -2118,7 +2119,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
Context);
if (getLangOpts().CPlusPlus)
return MergeCXXFunctionDecl(New, Old);
return MergeCXXFunctionDecl(New, Old, S);
return false;
}
@@ -5698,7 +5699,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (Redeclaration) {
// NewFD and OldDecl represent declarations that need to be
// merged.
if (MergeFunctionDecl(NewFD, OldDecl)) {
if (MergeFunctionDecl(NewFD, OldDecl, S)) {
NewFD->setInvalidDecl();
return Redeclaration;
}

View File

@@ -372,7 +372,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
// function, once we already know that they have the same
// type. Subroutine of MergeFunctionDecl. Returns true if there was an
// error, false otherwise.
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Scope *S) {
bool Invalid = false;
// C++ [dcl.fct.default]p4:
@@ -397,7 +398,16 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
ParmVarDecl *OldParam = Old->getParamDecl(p);
ParmVarDecl *NewParam = New->getParamDecl(p);
if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) {
bool OldParamHasDfl = OldParam->hasDefaultArg();
bool NewParamHasDfl = NewParam->hasDefaultArg();
NamedDecl *ND = Old;
if (S && !isDeclInScope(ND, New->getDeclContext(), S))
// Ignore default parameters of old decl if they are not in
// the same scope.
OldParamHasDfl = false;
if (OldParamHasDfl && NewParamHasDfl) {
unsigned DiagDefaultParamID =
diag::err_param_default_argument_redefinition;
@@ -443,7 +453,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
Diag(OldParam->getLocation(), diag::note_previous_definition)
<< OldParam->getDefaultArgRange();
} else if (OldParam->hasDefaultArg()) {
} else if (OldParamHasDfl) {
// Merge the old default argument into the new parameter.
// It's important to use getInit() here; getDefaultArg()
// strips off any top-level ExprWithCleanups.
@@ -453,7 +463,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
OldParam->getUninstantiatedDefaultArg());
else
NewParam->setDefaultArg(OldParam->getInit());
} else if (NewParam->hasDefaultArg()) {
} else if (NewParamHasDfl) {
if (New->getDescribedFunctionTemplate()) {
// Paragraph 4, quoted above, only applies to non-template functions.
Diag(NewParam->getLocation(),

View File

@@ -63,3 +63,14 @@ void f3() {
B *bs = new B[2];
delete bs;
}
void f4() {
void g4(int a, int b = 7);
{
void g4(int a, int b = 5);
}
void g4(int a = 5, int b);
// CHECK: call void @_Z2g4ii(i32 5, i32 7)
g4();
}

View File

@@ -32,3 +32,21 @@ void k(Y y = 17); // expected-error{{no viable conversion}} \
void kk(Y = 17); // expected-error{{no viable conversion}} \
// expected-note{{passing argument to parameter here}}
int l () {
int m(int i, int j, int k = 3);
if (1)
{
int m(int i, int j = 2, int k = 4);
m(8);
}
return 0;
}
int i () {
void j (int f = 4);
{
void j (int f); // expected-note{{'j' declared here}}
j(); // expected-error{{too few arguments to function call, expected 1, have 0}}
}
}