Skip to content

Commit eb5cf14

Browse files
authored
Merge branch 'main' into nonuniform_capabilities
2 parents 5681628 + eac2c18 commit eb5cf14

File tree

37 files changed

+969
-148
lines changed

37 files changed

+969
-148
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ Bug Fixes to C++ Support
574574
(#GH95854).
575575
- Fixed an assertion failure when evaluating an invalid expression in an array initializer. (#GH112140)
576576
- Fixed an assertion failure in range calculations for conditional throw expressions. (#GH111854)
577+
- Clang now correctly ignores previous partial specializations of member templates explicitly specialized for
578+
an implicitly instantiated class template specialization. (#GH51051)
577579

578580
Bug Fixes to AST Handling
579581
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Index/USRGeneration.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
namespace clang {
1616
class ASTContext;
1717
class Decl;
18+
class LangOptions;
1819
class MacroDefinitionRecord;
1920
class Module;
2021
class SourceLocation;
@@ -30,6 +31,8 @@ static inline StringRef getUSRSpacePrefix() {
3031
/// Generate a USR for a Decl, including the USR prefix.
3132
/// \returns true if the results should be ignored, false otherwise.
3233
bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf);
34+
bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,
35+
const LangOptions &LangOpts);
3336

3437
/// Generate a USR fragment for an Objective-C class.
3538
void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS,
@@ -75,7 +78,10 @@ bool generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
7578
/// Generates a USR for a type.
7679
///
7780
/// \return true on error, false on success.
78-
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl<char> &Buf);
81+
bool generateUSRForType(QualType T, ASTContext &Ctx,
82+
SmallVectorImpl<char> &Buf);
83+
bool generateUSRForType(QualType T, ASTContext &Ctx, SmallVectorImpl<char> &Buf,
84+
const LangOptions &LangOpts);
7985

8086
/// Generate a USR for a module, including the USR prefix.
8187
/// \returns true on error, false on success.

clang/lib/Index/USRGeneration.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,17 @@ namespace {
6262
class USRGenerator : public ConstDeclVisitor<USRGenerator> {
6363
SmallVectorImpl<char> &Buf;
6464
llvm::raw_svector_ostream Out;
65-
bool IgnoreResults;
6665
ASTContext *Context;
67-
bool generatedLoc;
66+
const LangOptions &LangOpts;
67+
bool IgnoreResults = false;
68+
bool generatedLoc = false;
6869

6970
llvm::DenseMap<const Type *, unsigned> TypeSubstitutions;
7071

7172
public:
72-
explicit USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf)
73-
: Buf(Buf),
74-
Out(Buf),
75-
IgnoreResults(false),
76-
Context(Ctx),
77-
generatedLoc(false)
78-
{
73+
USRGenerator(ASTContext *Ctx, SmallVectorImpl<char> &Buf,
74+
const LangOptions &LangOpts)
75+
: Buf(Buf), Out(Buf), Context(Ctx), LangOpts(LangOpts) {
7976
// Add the USR space prefix.
8077
Out << getUSRSpacePrefix();
8178
}
@@ -246,14 +243,13 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
246243
} else
247244
Out << "@F@";
248245

249-
PrintingPolicy Policy(Context->getLangOpts());
246+
PrintingPolicy Policy(LangOpts);
250247
// Forward references can have different template argument names. Suppress the
251248
// template argument names in constructors to make their USR more stable.
252249
Policy.SuppressTemplateArgsInCXXConstructors = true;
253250
D->getDeclName().print(Out, Policy);
254251

255-
ASTContext &Ctx = *Context;
256-
if ((!Ctx.getLangOpts().CPlusPlus || D->isExternC()) &&
252+
if ((!LangOpts.CPlusPlus || D->isExternC()) &&
257253
!D->hasAttr<OverloadableAttr>())
258254
return;
259255

@@ -657,9 +653,10 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) {
657653
return IgnoreResults;
658654
}
659655

660-
static void printQualifier(llvm::raw_ostream &Out, ASTContext &Ctx, NestedNameSpecifier *NNS) {
656+
static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
657+
NestedNameSpecifier *NNS) {
661658
// FIXME: Encode the qualifier, don't just print it.
662-
PrintingPolicy PO(Ctx.getLangOpts());
659+
PrintingPolicy PO(LangOpts);
663660
PO.SuppressTagKeyword = true;
664661
PO.SuppressUnwrittenScope = true;
665662
PO.ConstantArraySizeAsWritten = false;
@@ -948,7 +945,7 @@ void USRGenerator::VisitType(QualType T) {
948945
}
949946
if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
950947
Out << '^';
951-
printQualifier(Out, Ctx, DNT->getQualifier());
948+
printQualifier(Out, LangOpts, DNT->getQualifier());
952949
Out << ':' << DNT->getIdentifier()->getName();
953950
return;
954951
}
@@ -1090,7 +1087,7 @@ void USRGenerator::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl
10901087
return;
10911088
VisitDeclContext(D->getDeclContext());
10921089
Out << "@UUV@";
1093-
printQualifier(Out, D->getASTContext(), D->getQualifier());
1090+
printQualifier(Out, LangOpts, D->getQualifier());
10941091
EmitDeclName(D);
10951092
}
10961093

@@ -1099,7 +1096,7 @@ void USRGenerator::VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenam
10991096
return;
11001097
VisitDeclContext(D->getDeclContext());
11011098
Out << "@UUT@";
1102-
printQualifier(Out, D->getASTContext(), D->getQualifier());
1099+
printQualifier(Out, LangOpts, D->getQualifier());
11031100
Out << D->getName(); // Simple name.
11041101
}
11051102

@@ -1190,6 +1187,13 @@ bool clang::index::generateUSRForDecl(const Decl *D,
11901187
SmallVectorImpl<char> &Buf) {
11911188
if (!D)
11921189
return true;
1190+
return generateUSRForDecl(D, Buf, D->getASTContext().getLangOpts());
1191+
}
1192+
1193+
bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf,
1194+
const LangOptions &LangOpts) {
1195+
if (!D)
1196+
return true;
11931197
// We don't ignore decls with invalid source locations. Implicit decls, like
11941198
// C++'s operator new function, can have invalid locations but it is fine to
11951199
// create USRs that can identify them.
@@ -1203,7 +1207,7 @@ bool clang::index::generateUSRForDecl(const Decl *D,
12031207
return false;
12041208
}
12051209
}
1206-
USRGenerator UG(&D->getASTContext(), Buf);
1210+
USRGenerator UG(&D->getASTContext(), Buf, LangOpts);
12071211
UG.Visit(D);
12081212
return UG.ignoreResults();
12091213
}
@@ -1240,11 +1244,17 @@ bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
12401244

12411245
bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
12421246
SmallVectorImpl<char> &Buf) {
1247+
return generateUSRForType(T, Ctx, Buf, Ctx.getLangOpts());
1248+
}
1249+
1250+
bool clang::index::generateUSRForType(QualType T, ASTContext &Ctx,
1251+
SmallVectorImpl<char> &Buf,
1252+
const LangOptions &LangOpts) {
12431253
if (T.isNull())
12441254
return true;
12451255
T = T.getCanonicalType();
12461256

1247-
USRGenerator UG(&Ctx, Buf);
1257+
USRGenerator UG(&Ctx, Buf, LangOpts);
12481258
UG.VisitType(T);
12491259
return UG.ignoreResults();
12501260
}

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4381,8 +4381,20 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
43814381
SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
43824382
Template->getPartialSpecializations(PartialSpecs);
43834383

4384-
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
4385-
VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
4384+
for (VarTemplatePartialSpecializationDecl *Partial : PartialSpecs) {
4385+
// C++ [temp.spec.partial.member]p2:
4386+
// If the primary member template is explicitly specialized for a given
4387+
// (implicit) specialization of the enclosing class template, the partial
4388+
// specializations of the member template are ignored for this
4389+
// specialization of the enclosing class template. If a partial
4390+
// specialization of the member template is explicitly specialized for a
4391+
// given (implicit) specialization of the enclosing class template, the
4392+
// primary member template and its other partial specializations are still
4393+
// considered for this specialization of the enclosing class template.
4394+
if (Template->getMostRecentDecl()->isMemberSpecialization() &&
4395+
!Partial->getMostRecentDecl()->isMemberSpecialization())
4396+
continue;
4397+
43864398
TemplateDeductionInfo Info(FailedCandidates.getLocation());
43874399

43884400
if (TemplateDeductionResult Result =

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3978,11 +3978,24 @@ bool Sema::usesPartialOrExplicitSpecialization(
39783978
return true;
39793979

39803980
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
3981-
ClassTemplateSpec->getSpecializedTemplate()
3982-
->getPartialSpecializations(PartialSpecs);
3983-
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
3981+
ClassTemplateDecl *CTD = ClassTemplateSpec->getSpecializedTemplate();
3982+
CTD->getPartialSpecializations(PartialSpecs);
3983+
for (ClassTemplatePartialSpecializationDecl *CTPSD : PartialSpecs) {
3984+
// C++ [temp.spec.partial.member]p2:
3985+
// If the primary member template is explicitly specialized for a given
3986+
// (implicit) specialization of the enclosing class template, the partial
3987+
// specializations of the member template are ignored for this
3988+
// specialization of the enclosing class template. If a partial
3989+
// specialization of the member template is explicitly specialized for a
3990+
// given (implicit) specialization of the enclosing class template, the
3991+
// primary member template and its other partial specializations are still
3992+
// considered for this specialization of the enclosing class template.
3993+
if (CTD->getMostRecentDecl()->isMemberSpecialization() &&
3994+
!CTPSD->getMostRecentDecl()->isMemberSpecialization())
3995+
continue;
3996+
39843997
TemplateDeductionInfo Info(Loc);
3985-
if (DeduceTemplateArguments(PartialSpecs[I],
3998+
if (DeduceTemplateArguments(CTPSD,
39863999
ClassTemplateSpec->getTemplateArgs().asArray(),
39874000
Info) == TemplateDeductionResult::Success)
39884001
return true;
@@ -4025,8 +4038,21 @@ getPatternForClassTemplateSpecialization(
40254038
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
40264039
Template->getPartialSpecializations(PartialSpecs);
40274040
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
4028-
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
4029-
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
4041+
for (ClassTemplatePartialSpecializationDecl *Partial : PartialSpecs) {
4042+
// C++ [temp.spec.partial.member]p2:
4043+
// If the primary member template is explicitly specialized for a given
4044+
// (implicit) specialization of the enclosing class template, the
4045+
// partial specializations of the member template are ignored for this
4046+
// specialization of the enclosing class template. If a partial
4047+
// specialization of the member template is explicitly specialized for a
4048+
// given (implicit) specialization of the enclosing class template, the
4049+
// primary member template and its other partial specializations are
4050+
// still considered for this specialization of the enclosing class
4051+
// template.
4052+
if (Template->getMostRecentDecl()->isMemberSpecialization() &&
4053+
!Partial->getMostRecentDecl()->isMemberSpecialization())
4054+
continue;
4055+
40304056
TemplateDeductionInfo Info(FailedCandidates.getLocation());
40314057
if (TemplateDeductionResult Result = S.DeduceTemplateArguments(
40324058
Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info);
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
4+
template<typename T>
5+
struct A {
6+
template<typename U>
7+
struct B {
8+
static constexpr int y = 0;
9+
};
10+
11+
template<typename U>
12+
struct B<U*> {
13+
static constexpr int y = 1;
14+
};
15+
16+
template<typename U>
17+
static constexpr int x = 0;
18+
19+
template<typename U>
20+
static constexpr int x<U*> = 1;
21+
};
22+
23+
template<typename T>
24+
template<typename U>
25+
struct A<T>::B<U[]> {
26+
static constexpr int y = 2;
27+
};
28+
29+
template<typename T>
30+
template<typename U>
31+
constexpr int A<T>::x<U[]> = 2;
32+
33+
static_assert(A<short>::B<int>::y == 0);
34+
static_assert(A<short>::B<int*>::y == 1);
35+
static_assert(A<short>::B<int[]>::y == 2);
36+
static_assert(A<short>::x<int> == 0);
37+
static_assert(A<short>::x<int*> == 1);
38+
static_assert(A<short>::x<int[]> == 2);
39+
40+
template<>
41+
template<typename U>
42+
struct A<int>::B {
43+
static constexpr int y = 3;
44+
};
45+
46+
template<>
47+
template<typename U>
48+
struct A<int>::B<U&> {
49+
static constexpr int y = 4;
50+
};
51+
52+
template<>
53+
template<typename U>
54+
struct A<long>::B<U&> {
55+
static constexpr int y = 5;
56+
};
57+
58+
template<>
59+
template<typename U>
60+
constexpr int A<int>::x = 3;
61+
62+
template<>
63+
template<typename U>
64+
constexpr int A<int>::x<U&> = 4;
65+
66+
template<>
67+
template<typename U>
68+
constexpr int A<long>::x<U&> = 5;
69+
70+
static_assert(A<int>::B<int>::y == 3);
71+
static_assert(A<int>::B<int*>::y == 3);
72+
static_assert(A<int>::B<int[]>::y == 3);
73+
static_assert(A<int>::B<int&>::y == 4);
74+
static_assert(A<int>::x<int> == 3);
75+
static_assert(A<int>::x<int*> == 3);
76+
static_assert(A<int>::x<int[]> == 3);
77+
static_assert(A<int>::x<int&> == 4);
78+
static_assert(A<long>::B<int>::y == 0);
79+
static_assert(A<long>::B<int*>::y == 1);
80+
static_assert(A<long>::B<int[]>::y == 2);
81+
static_assert(A<long>::B<int&>::y == 5);
82+
static_assert(A<long>::x<int> == 0);
83+
static_assert(A<long>::x<int*> == 1);
84+
static_assert(A<long>::x<int[]> == 2);
85+
static_assert(A<long>::x<int&> == 5);

flang/tools/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ add_subdirectory(flang-driver)
1212
add_subdirectory(tco)
1313
add_subdirectory(f18-parse-demo)
1414
add_subdirectory(fir-opt)
15+
add_subdirectory(fir-lsp-server)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Core
3+
Support
4+
AsmParser
5+
)
6+
7+
add_flang_tool(fir-lsp-server fir-lsp-server.cpp)
8+
9+
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
10+
get_property(extension_libs GLOBAL PROPERTY MLIR_EXTENSION_LIBS)
11+
target_link_libraries(fir-lsp-server PRIVATE
12+
CUFDialect
13+
FIRDialect
14+
HLFIRDialect
15+
MLIRLspServerLib
16+
${dialect_libs}
17+
${extension_libs})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "mlir/Tools/mlir-lsp-server/MlirLspServerMain.h"
2+
#include "flang/Optimizer/Support/InitFIR.h"
3+
4+
int main(int argc, char **argv) {
5+
mlir::DialectRegistry registry;
6+
fir::support::registerNonCodegenDialects(registry);
7+
fir::support::addFIRExtensions(registry);
8+
return mlir::failed(mlir::MlirLspServerMain(argc, argv, registry));
9+
}

0 commit comments

Comments
 (0)