diff options
author | James Molloy <james.molloy@arm.com> | 2012-03-13 08:55:35 +0000 |
---|---|---|
committer | James Molloy <james.molloy@arm.com> | 2012-03-13 08:55:35 +0000 |
commit | 9cda03ff7fc40b727d0cc44b1702dbae09d63f42 (patch) | |
tree | c6810bc9b1c12832eb2e96551581f15c0fb1274f | |
parent | e37f484ab9a65ce4e5f90adcfa20add4215e0783 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152621 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/default-arguments.cpp | 11 | ||||
-rw-r--r-- | test/SemaCXX/default1.cpp | 18 |
5 files changed, 55 insertions, 14 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index cd200f327a..972b311d7f 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 57b0e9d9c5..c1ef732a92 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b6866d04e4..79a5d4c98c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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(), diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp index 6560d3514f..206d4d6c88 100644 --- a/test/CodeGenCXX/default-arguments.cpp +++ b/test/CodeGenCXX/default-arguments.cpp @@ -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(); +} diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp index e9d8a2f767..ae6ef9791c 100644 --- a/test/SemaCXX/default1.cpp +++ b/test/SemaCXX/default1.cpp @@ -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}} + } +} |