-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates #80842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates #80842
Conversation
@llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) ChangesAccording to [[expr.prim.id.qual] p3](http://eel.is/c++draft/expr.prim.id.qual#3): Meaning, the out-of-line definition of template<typename T>
struct A
{
void f();
};
template<typename T>
using B = A<T>;
template<typename T>
void B<T>::f() { } // error: a declarative nested name specifier cannot name a type alias template This patch diagnoses such cases as an extension (in group Full diff: https://github.com/llvm/llvm-project/pull/80842.diff 4 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183..d02fddd069341 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8250,6 +8250,9 @@ def err_not_tag_in_scope : Error<
def ext_template_after_declarative_nns : ExtWarn<
"'template' cannot be used after a declarative nested name specifier">,
InGroup<DiagGroup<"template-in-declaration-name">>;
+def ext_alias_template_in_declarative_nns : ExtWarn<
+ "a declarative nested name specifier cannot name an alias template">,
+ InGroup<DiagGroup<"alias-template-in-declaration-name">>;
def err_no_typeid_with_fno_rtti : Error<
"use of typeid requires -frtti">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389b..464f3738b0ba5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6207,6 +6207,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
SourceLocation Loc,
TemplateIdAnnotation *TemplateId,
bool IsMemberSpecialization) {
+ assert(SS.isValid() && "diagnoseQualifiedDeclaration called for declaration "
+ "without nested-name-specifier");
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
<< FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
- while (SpecLoc.getPrefix()) {
+ do {
if (SpecLoc.getNestedNameSpecifier()->getKind() ==
NestedNameSpecifier::TypeSpecWithTemplate)
Diag(Loc, diag::ext_template_after_declarative_nns)
<< FixItHint::CreateRemoval(
SpecLoc.getTypeLoc().getTemplateKeywordLoc());
- SpecLoc = SpecLoc.getPrefix();
- }
- // C++11 [dcl.meaning]p1:
- // [...] "The nested-name-specifier of the qualified declarator-id shall
- // not begin with a decltype-specifer"
- if (isa_and_nonnull<DecltypeType>(
- SpecLoc.getNestedNameSpecifier()->getAsType()))
- Diag(Loc, diag::err_decltype_in_declarator)
- << SpecLoc.getTypeLoc().getSourceRange();
+ if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+ if (const auto *TST = T->getAsAdjusted<TemplateSpecializationType>()) {
+ // C++23 [expr.prim.id.qual]p3:
+ // [...] If a nested-name-specifier N is declarative and has a
+ // simple-template-id with a template argument list A that involves a
+ // template parameter, let T be the template nominated by N without A.
+ // T shall be a class template.
+ if (TST->isDependentType() && TST->isTypeAlias())
+ Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+ << SpecLoc.getLocalSourceRange();
+ } else if (T->isDecltypeType()) {
+ // C++23 [expr.prim.id.qual]p2:
+ // [...] A declarative nested-name-specifier shall not have a
+ // decltype-specifier.
+ //
+ // FIXME: This wording appears to be defective, as it does not
+ // forbid declarative nested-name-specifiers that begin with a
+ // pack-index-specifier.
+ Diag(Loc, diag::err_decltype_in_declarator)
+ << SpecLoc.getTypeLoc().getSourceRange();
+ }
+ }
+ } while ((SpecLoc = SpecLoc.getPrefix()));
return false;
}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
new file mode 100644
index 0000000000000..ba89d2c96c7bb
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify %s
+
+template<typename T>
+struct A {
+ void f();
+};
+
+template<typename T>
+using B = A<T>;
+
+template<typename T>
+void B<T>::f() { } // expected-warning {{a declarative nested name specifier cannot name an alias template}}
+
+template<>
+void B<int>::f() { } // ok, template argument list of simple-template-id doesn't involve template parameters
+
+namespace N {
+
+ template<typename T>
+ struct D {
+ void f();
+ };
+
+ template<typename T>
+ using E = C<T>;
+}
+
+template<typename T>
+void N::E<T>::f() { } // expected-warning {{a declarative nested name specifier cannot name an alias template}}
diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
index 82983f05fe878..910dab11ee5e1 100644
--- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
@@ -26,5 +26,5 @@ namespace Example2 {
void g();
};
template<class T> using B = A<T>;
- template<class T> void B<T>::g() {} // ok.
+ template<class T> void B<T>::g() {} // // expected-warning {{a declarative nested name specifier cannot name an alias template}}
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added other reviewers, this part of naming is something that I need other eyes on.
13abf4c
to
c7457d7
Compare
@erichkeane Should i wait for additional reviews, or can this be merged? |
I think we're good, feel free to resolve your conflict and commit. |
c7457d7
to
3cef590
Compare
According to [expr.prim.id.qual] p3:
Meaning, the out-of-line definition of
A::f
in the following example is ill-formed:This patch diagnoses such cases as an extension (in group
alias-template-in-declaration-name
).