From: Richard Smith Date: Fri, 14 Jun 2019 20:01:54 +0000 (+0000) Subject: PR42071: Reject weird names for non-type template parameters. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ba78be77a4efee70ff070aabccb9903e712fa5ac;p=clang PR42071: Reject weird names for non-type template parameters. Also reject default arguments appearing in invalid locations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@363447 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5b4e18673f..94e819c5d5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -250,6 +250,8 @@ def err_bad_variable_name : Error< "%0 cannot be the name of a variable or data member">; def err_bad_parameter_name : Error< "%0 cannot be the name of a parameter">; +def err_bad_parameter_name_template_id : Error< + "parameter name cannot have template arguments">; def err_parameter_name_omitted : Error<"parameter name omitted">; def err_anyx86_interrupt_attribute : Error< "%select{x86|x86-64}0 'interrupt' attribute only applies to functions that " diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b34f5c9196..c6fddbbb9c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2083,7 +2083,9 @@ public: QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); - Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); + Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, + bool IsDefinition); + void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ce6fd41236..d346105e7a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12453,6 +12453,45 @@ void Sema::ActOnDocumentableDecls(ArrayRef Group) { } } +/// Common checks for a parameter-declaration that should apply to both function +/// parameters and non-type template parameters. +void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { + // Check that there are no default arguments inside the type of this + // parameter. + if (getLangOpts().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) + << D.getCXXScopeSpec().getRange(); + } + + // [dcl.meaning]p1: An unqualified-id occurring in a declarator-id shall be a + // simple identifier except [...irrelevant cases...]. + switch (D.getName().getKind()) { + case UnqualifiedIdKind::IK_Identifier: + break; + + case UnqualifiedIdKind::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_ConversionFunctionId: + case UnqualifiedIdKind::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_ConstructorName: + case UnqualifiedIdKind::IK_DestructorName: + case UnqualifiedIdKind::IK_ImplicitSelfParam: + case UnqualifiedIdKind::IK_DeductionGuideName: + Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) + << GetNameForDeclarator(D).getName(); + break; + + case UnqualifiedIdKind::IK_TemplateId: + case UnqualifiedIdKind::IK_ConstructorTemplateId: + // GetNameForDeclarator would not produce a useful name in this case. + Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name_template_id); + break; + } +} + /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { @@ -12493,34 +12532,13 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { DiagnoseFunctionSpecifiers(DS); + CheckFunctionOrTemplateParamDeclarator(S, D); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType parmDeclType = TInfo->getType(); - if (getLangOpts().CPlusPlus) { - // Check that there are no default arguments inside the type of this - // parameter. - CheckExtraCXXDefaultArguments(D); - - // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). - if (D.getCXXScopeSpec().isSet()) { - Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) - << D.getCXXScopeSpec().getRange(); - D.getCXXScopeSpec().clear(); - } - } - - // Ensure we have a valid name - IdentifierInfo *II = nullptr; - if (D.hasName()) { - II = D.getIdentifier(); - if (!II) { - Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) - << GetNameForDeclarator(D).getName(); - D.setInvalidType(true); - } - } - // Check for redeclaration of parameters, e.g. int foo(int x, int x); + IdentifierInfo *II = D.getIdentifier(); if (II) { LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, ForVisibleRedeclaration); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 03240655ee..74a891bcb7 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1181,6 +1181,8 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, Invalid = true; } + CheckFunctionOrTemplateParamDeclarator(S, D); + IdentifierInfo *ParamName = D.getIdentifier(); bool IsParameterPack = D.hasEllipsis(); NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create( diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 64c485fc0e..07316782a8 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -253,3 +253,11 @@ namespace class_scope_instantiation { void f(double); }; } + +namespace PR42071 { + template> struct A; // expected-error {{parameter name cannot have template arguments}} + template struct B; // expected-error {{'operator+' cannot be the name of a parameter}} + struct Q {}; + template struct C; // expected-error {{parameter declarator cannot be qualified}} + template struct D; // expected-error {{default arguments can only be specified for parameters in a function declaration}} +}