diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index caf7affd0cc..4e5e307be61 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -404,6 +404,17 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { } } +static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { + for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) { + const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1); + if (!PVD->hasDefaultArg()) + return false; + if (!PVD->hasInheritedDefaultArg()) + return true; + } + return false; +} + /// MergeCXXFunctionDecl - Merge two declarations of the same C++ /// function, once we already know that they have the same /// type. Subroutine of MergeFunctionDecl. Returns true if there was an @@ -578,6 +589,17 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Invalid = true; } + // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default + // argument expression, that declaration shall be a deļ¬nition and shall be + // the only declaration of the function or function template in the + // translation unit. + if (Old->getFriendObjectKind() == Decl::FOK_Undeclared && + functionDeclHasDefaultArgument(Old)) { + Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); + Diag(Old->getLocation(), diag::note_previous_declaration); + Invalid = true; + } + if (CheckEquivalentExceptionSpec(Old, New)) Invalid = true; @@ -11377,6 +11399,18 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, else FD = cast<FunctionDecl>(ND); + // C++11 [dcl.fct.default]p4: If a friend declaration specifies a + // default argument expression, that declaration shall be a definition + // and shall be the only declaration of the function or function + // template in the translation unit. + if (functionDeclHasDefaultArgument(FD)) { + if (FunctionDecl *OldFD = FD->getPreviousDecl()) { + Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); + Diag(OldFD->getLocation(), diag::note_previous_declaration); + } else if (!D.isFunctionDefinition()) + Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def); + } + // Mark templated-scope function declarations as unsupported. if (FD->getNumTemplateParameterLists()) FrD->setUnsupportedFriend(true); |