diff options
author | Faisal Vali <faisalv@yahoo.com> | 2017-12-22 03:50:55 +0000 |
---|---|---|
committer | Faisal Vali <faisalv@yahoo.com> | 2017-12-22 03:50:55 +0000 |
commit | a223d1c856dbab543ecf52a69071ab57f2c0ee1c (patch) | |
tree | 0ae3a1566e1e230a3ef37989ccdf7902be053288 /clang/lib/Sema/SemaTemplate.cpp | |
parent | 16b386de15782a086778a4a66447058310483713 (diff) | |
download | bcm5719-llvm-a223d1c856dbab543ecf52a69071ab57f2c0ee1c.tar.gz bcm5719-llvm-a223d1c856dbab543ecf52a69071ab57f2c0ee1c.zip |
Diagnose the various invalid decl-specifiers on nontype template parameters.
The standard correctly forbids various decl-specifiers that dont make sense on non-type template parameters - such as the extern in:
template<extern int> struct X;
This patch implements those restrictions (in a fashion similar to the corresponding checks on function parameters within ActOnParamDeclarator).
Credit goes to miyuki (Mikhail Maltsev) for drawing attention to this issue, authoring the initial versions of this patch, and supporting the effort to re-engineer it slightly. Thank you!
For details of how this patch evolved please see: https://reviews.llvm.org/D40705
llvm-svn: 321339
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index c70a8ba8f12..4ce4a90e551 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -929,6 +929,60 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, Expr *Default) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + // Check that we have valid decl-specifiers specified. + auto CheckValidDeclSpecifiers = [this, &D] { + // C++ [temp.param] + // p1 + // template-parameter:
+ // ...
+ // parameter-declaration
+ // p2 + // ... A storage class shall not be specified in a template-parameter + // declaration. + // [dcl.typedef]p1: + // The typedef specifier [...] shall not be used in the decl-specifier-seq + // of a parameter-declaration + const DeclSpec &DS = D.getDeclSpec(); + auto EmitDiag = [this](SourceLocation Loc) { + Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm) + << FixItHint::CreateRemoval(Loc); + }; + if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) + EmitDiag(DS.getStorageClassSpecLoc()); + + if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec()) + EmitDiag(DS.getThreadStorageClassSpecLoc()); + + // [dcl.inline]p1: + // The inline specifier can be applied only to the declaration or + // definition of a variable or function. + + if (DS.isInlineSpecified()) + EmitDiag(DS.getInlineSpecLoc()); + + // [dcl.constexpr]p1: + // The constexpr specifier shall be applied only to the definition of a + // variable or variable template or the declaration of a function or + // function template. + + if (DS.isConstexprSpecified()) + EmitDiag(DS.getConstexprSpecLoc()); + + // [dcl.fct.spec]p1: + // Function-specifiers can be used only in function declarations. + + if (DS.isVirtualSpecified()) + EmitDiag(DS.getVirtualSpecLoc()); + + if (DS.isExplicitSpecified()) + EmitDiag(DS.getExplicitSpecLoc()); + + if (DS.isNoreturnSpecified()) + EmitDiag(DS.getNoreturnSpecLoc()); + }; + + CheckValidDeclSpecifiers(); + if (TInfo->getType()->isUndeducedType()) { Diag(D.getIdentifierLoc(), diag::warn_cxx14_compat_template_nontype_parm_auto_type) |