diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-14 20:01:54 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-06-14 20:01:54 +0000 |
| commit | da70fc0c5f5bb79fa46120710b7b66d1b7e7ca7e (patch) | |
| tree | d7f567ca09b40a58236704dff545451e5145954a | |
| parent | 7fa2b74e988e8da6a1d0c27d4c6567f26aec03e6 (diff) | |
| download | bcm5719-llvm-da70fc0c5f5bb79fa46120710b7b66d1b7e7ca7e.tar.gz bcm5719-llvm-da70fc0c5f5bb79fa46120710b7b66d1b7e7ca7e.zip | |
PR42071: Reject weird names for non-type template parameters.
Also reject default arguments appearing in invalid locations.
llvm-svn: 363447
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 66 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Parser/cxx-template-decl.cpp | 8 |
5 files changed, 57 insertions, 25 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5b4e18673f2..94e819c5d59 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b34f5c9196f..c6fddbbb9c6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ce6fd412361..d346105e7ab 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12453,6 +12453,45 @@ void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> 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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 03240655ee3..74a891bcb70 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 64c485fc0ec..07316782a83 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -253,3 +253,11 @@ namespace class_scope_instantiation { void f(double); }; } + +namespace PR42071 { + template<int SomeTemplateName<void>> struct A; // expected-error {{parameter name cannot have template arguments}} + template<int operator+> struct B; // expected-error {{'operator+' cannot be the name of a parameter}} + struct Q {}; + template<int Q::N> struct C; // expected-error {{parameter declarator cannot be qualified}} + template<int f(int a = 0)> struct D; // expected-error {{default arguments can only be specified for parameters in a function declaration}} +} |

