mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
[clang] remove ClassScopeFunctionSpecializationDecl (#66636)
This removes the `ClassScopeFunctionSpecializationDecl` `Decl` node, and instead uses `DependentFunctionTemplateSpecializationInfo` to handle such declarations. `DependentFunctionTemplateSpecializationInfo` is also changed to store a `const ASTTemplateArgumentListInfo*` to be more in line with `FunctionTemplateSpecializationInfo`. This also changes `FunctionDecl::isFunctionTemplateSpecialization` to return `true` for dependent specializations, and `FunctionDecl::getTemplateSpecializationKind`/`FunctionDecl::getTemplateSpecializationKindForInstantiation` to return `TSK_ExplicitSpecialization` for non-friend dependent specializations (the same behavior as dependent class scope `ClassTemplateSepcializationDecl` & `VarTemplateSepcializationDecl`).
This commit is contained in:
parent
859f2d0323
commit
3a3b84b180
@ -67,11 +67,9 @@ AST_MATCHER_P(CallExpr, hasLastArgument,
|
||||
// function had parameters defined (this is useful to check if there is only one
|
||||
// variadic argument).
|
||||
AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) {
|
||||
if (Node.getMethodDecl()->isFunctionTemplateSpecialization())
|
||||
return Node.getNumArgs() == Node.getMethodDecl()
|
||||
->getPrimaryTemplate()
|
||||
->getTemplatedDecl()
|
||||
->getNumParams();
|
||||
if (const FunctionTemplateDecl *Primary =
|
||||
Node.getMethodDecl()->getPrimaryTemplate())
|
||||
return Node.getNumArgs() == Primary->getTemplatedDecl()->getNumParams();
|
||||
|
||||
return Node.getNumArgs() == Node.getMethodDecl()->getNumParams();
|
||||
}
|
||||
|
@ -715,13 +715,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *D) {
|
||||
if (auto *Args = D->getTemplateArgsAsWritten())
|
||||
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitDeclRefExpr(DeclRefExpr *E) {
|
||||
H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
|
||||
return true;
|
||||
@ -752,8 +745,6 @@ public:
|
||||
}
|
||||
if (auto *Args = D->getTemplateSpecializationArgsAsWritten())
|
||||
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
|
||||
if (auto *I = D->getDependentSpecializationInfo())
|
||||
H.addAngleBracketTokens(I->getLAngleLoc(), I->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,11 @@ C++ Specific Potentially Breaking Changes
|
||||
(`#49884 <https://github.com/llvm/llvm-project/issues/49884>`_), and
|
||||
(`#61273 <https://github.com/llvm/llvm-project/issues/61273>`_)
|
||||
|
||||
- The `ClassScopeFunctionSpecializationDecl` AST node has been removed. Dependent class scope
|
||||
explicit function template specializations now use `DependentFunctionTemplateSpecializationInfo`
|
||||
to store candidate primary templates and explicit template arguments. This should not impact users
|
||||
of Clang as a compiler, but it may break assumptions in Clang-based tools iterating over the AST.
|
||||
|
||||
ABI Changes in This Version
|
||||
---------------------------
|
||||
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
|
||||
|
@ -426,8 +426,12 @@ public:
|
||||
}
|
||||
|
||||
void VisitFunctionDecl(const FunctionDecl *D) {
|
||||
if (const auto *FTSI = D->getTemplateSpecializationInfo())
|
||||
if (FunctionTemplateSpecializationInfo *FTSI =
|
||||
D->getTemplateSpecializationInfo())
|
||||
dumpTemplateArgumentList(*FTSI->TemplateArguments);
|
||||
else if (DependentFunctionTemplateSpecializationInfo *DFTSI =
|
||||
D->getDependentSpecializationInfo())
|
||||
dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten);
|
||||
|
||||
if (D->param_begin())
|
||||
for (const auto *Parameter : D->parameters())
|
||||
@ -578,11 +582,6 @@ public:
|
||||
dumpTemplateParameters(D->getTemplateParameters());
|
||||
}
|
||||
|
||||
void VisitClassScopeFunctionSpecializationDecl(
|
||||
const ClassScopeFunctionSpecializationDecl *D) {
|
||||
Visit(D->getSpecialization());
|
||||
dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
|
||||
}
|
||||
void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); }
|
||||
|
||||
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
|
||||
|
@ -2845,9 +2845,7 @@ public:
|
||||
|
||||
/// Determine whether this function is a function template
|
||||
/// specialization.
|
||||
bool isFunctionTemplateSpecialization() const {
|
||||
return getPrimaryTemplate() != nullptr;
|
||||
}
|
||||
bool isFunctionTemplateSpecialization() const;
|
||||
|
||||
/// If this function is actually a function template specialization,
|
||||
/// retrieve information about this function template specialization.
|
||||
@ -2930,9 +2928,9 @@ public:
|
||||
|
||||
/// Specifies that this function declaration is actually a
|
||||
/// dependent function template specialization.
|
||||
void setDependentTemplateSpecialization(ASTContext &Context,
|
||||
const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
void setDependentTemplateSpecialization(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo *
|
||||
getDependentSpecializationInfo() const;
|
||||
|
@ -583,7 +583,7 @@ public:
|
||||
/// \code
|
||||
/// template<typename> struct A {
|
||||
/// template<typename> void f();
|
||||
/// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl
|
||||
/// template<> void f<int>();
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
@ -682,82 +682,48 @@ public:
|
||||
/// Provides information about a dependent function-template
|
||||
/// specialization declaration.
|
||||
///
|
||||
/// Since explicit function template specialization and instantiation
|
||||
/// declarations can only appear in namespace scope, and you can only
|
||||
/// specialize a member of a fully-specialized class, the only way to
|
||||
/// get one of these is in a friend declaration like the following:
|
||||
/// This is used for function templates explicit specializations declared
|
||||
/// within class templates:
|
||||
///
|
||||
/// \code
|
||||
/// template<typename> struct A {
|
||||
/// template<typename> void f();
|
||||
/// template<> void f<int>(); // DependentFunctionTemplateSpecializationInfo
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// As well as dependent friend declarations naming function template
|
||||
/// specializations declared within class templates:
|
||||
///
|
||||
/// \code
|
||||
/// template \<class T> void foo(T);
|
||||
/// template \<class T> class A {
|
||||
/// friend void foo<>(T);
|
||||
/// friend void foo<>(T); // DependentFunctionTemplateSpecializationInfo
|
||||
/// };
|
||||
/// \endcode
|
||||
class DependentFunctionTemplateSpecializationInfo final
|
||||
: private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
|
||||
TemplateArgumentLoc,
|
||||
FunctionTemplateDecl *> {
|
||||
/// The number of potential template candidates.
|
||||
unsigned NumTemplates;
|
||||
|
||||
/// The number of template arguments.
|
||||
unsigned NumArgs;
|
||||
|
||||
/// The locations of the left and right angle brackets.
|
||||
SourceRange AngleLocs;
|
||||
|
||||
size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
|
||||
return NumArgs;
|
||||
}
|
||||
size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
|
||||
return NumTemplates;
|
||||
}
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
|
||||
public:
|
||||
friend TrailingObjects;
|
||||
|
||||
/// The number of candidates for the primary template.
|
||||
unsigned NumCandidates;
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Candidates,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsWritten);
|
||||
|
||||
public:
|
||||
/// The template arguments as written in the sources, if provided.
|
||||
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
|
||||
|
||||
static DependentFunctionTemplateSpecializationInfo *
|
||||
Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
Create(ASTContext &Context, const UnresolvedSetImpl &Candidates,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
/// Returns the number of function templates that this might
|
||||
/// be a specialization of.
|
||||
unsigned getNumTemplates() const { return NumTemplates; }
|
||||
|
||||
/// Returns the i'th template candidate.
|
||||
FunctionTemplateDecl *getTemplate(unsigned I) const {
|
||||
assert(I < getNumTemplates() && "template index out of range");
|
||||
return getTrailingObjects<FunctionTemplateDecl *>()[I];
|
||||
}
|
||||
|
||||
/// Returns the explicit template arguments that were given.
|
||||
const TemplateArgumentLoc *getTemplateArgs() const {
|
||||
return getTrailingObjects<TemplateArgumentLoc>();
|
||||
}
|
||||
|
||||
/// Returns the number of explicit template arguments that were given.
|
||||
unsigned getNumTemplateArgs() const { return NumArgs; }
|
||||
|
||||
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
|
||||
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
|
||||
}
|
||||
|
||||
/// Returns the nth template argument.
|
||||
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
|
||||
assert(I < getNumTemplateArgs() && "template arg index out of range");
|
||||
return getTemplateArgs()[I];
|
||||
}
|
||||
|
||||
SourceLocation getLAngleLoc() const {
|
||||
return AngleLocs.getBegin();
|
||||
}
|
||||
|
||||
SourceLocation getRAngleLoc() const {
|
||||
return AngleLocs.getEnd();
|
||||
/// Returns the candidates for the primary function template.
|
||||
ArrayRef<FunctionTemplateDecl *> getCandidates() const {
|
||||
return {getTrailingObjects<FunctionTemplateDecl *>(), NumCandidates};
|
||||
}
|
||||
};
|
||||
|
||||
@ -2613,70 +2579,6 @@ public:
|
||||
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
|
||||
};
|
||||
|
||||
/// Declaration of a function specialization at template class scope.
|
||||
///
|
||||
/// For example:
|
||||
/// \code
|
||||
/// template <class T>
|
||||
/// class A {
|
||||
/// template <class U> void foo(U a) { }
|
||||
/// template<> void foo(int a) { }
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// "template<> foo(int a)" will be saved in Specialization as a normal
|
||||
/// CXXMethodDecl. Then during an instantiation of class A, it will be
|
||||
/// transformed into an actual function specialization.
|
||||
///
|
||||
/// FIXME: This is redundant; we could store the same information directly on
|
||||
/// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo.
|
||||
class ClassScopeFunctionSpecializationDecl : public Decl {
|
||||
CXXMethodDecl *Specialization;
|
||||
const ASTTemplateArgumentListInfo *TemplateArgs;
|
||||
|
||||
ClassScopeFunctionSpecializationDecl(
|
||||
DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
|
||||
const ASTTemplateArgumentListInfo *TemplArgs)
|
||||
: Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
|
||||
Specialization(FD), TemplateArgs(TemplArgs) {}
|
||||
|
||||
ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
|
||||
: Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
|
||||
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
CXXMethodDecl *getSpecialization() const { return Specialization; }
|
||||
bool hasExplicitTemplateArgs() const { return TemplateArgs; }
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
return TemplateArgs;
|
||||
}
|
||||
|
||||
static ClassScopeFunctionSpecializationDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgumentListInfo &TemplateArgs) {
|
||||
return new (C, DC) ClassScopeFunctionSpecializationDecl(
|
||||
DC, Loc, FD,
|
||||
HasExplicitTemplateArgs
|
||||
? ASTTemplateArgumentListInfo::Create(C, TemplateArgs)
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
static ClassScopeFunctionSpecializationDecl *
|
||||
CreateDeserialized(ASTContext &Context, unsigned ID);
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
||||
static bool classofKind(Kind K) {
|
||||
return K == Decl::ClassScopeFunctionSpecialization;
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents a variable template specialization, which refers to
|
||||
/// a variable template with a given set of template arguments.
|
||||
///
|
||||
|
@ -1563,16 +1563,6 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
|
||||
}
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
|
||||
TRY_TO(TraverseDecl(D->getSpecialization()));
|
||||
|
||||
if (D->hasExplicitTemplateArgs()) {
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper(
|
||||
D->getTemplateArgsAsWritten()->getTemplateArgs(),
|
||||
D->getTemplateArgsAsWritten()->NumTemplateArgs));
|
||||
}
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(ExportDecl, {})
|
||||
@ -2154,6 +2144,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
|
||||
TALI->NumTemplateArgs));
|
||||
}
|
||||
}
|
||||
} else if (const DependentFunctionTemplateSpecializationInfo *DFSI =
|
||||
D->getDependentSpecializationInfo()) {
|
||||
if (const ASTTemplateArgumentListInfo *TALI =
|
||||
DFSI->TemplateArgumentsAsWritten) {
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
|
||||
TALI->NumTemplateArgs));
|
||||
}
|
||||
}
|
||||
|
||||
// Visit the function type itself, which can be either
|
||||
|
@ -102,7 +102,6 @@ def FriendTemplate : DeclNode<Decl>;
|
||||
def StaticAssert : DeclNode<Decl>;
|
||||
def Block : DeclNode<Decl, "blocks">, DeclContext;
|
||||
def Captured : DeclNode<Decl>, DeclContext;
|
||||
def ClassScopeFunctionSpecialization : DeclNode<Decl>;
|
||||
def Import : DeclNode<Decl>;
|
||||
def OMPThreadPrivate : DeclNode<Decl>;
|
||||
def OMPAllocate : DeclNode<Decl>;
|
||||
|
@ -5232,11 +5232,11 @@ def err_explicit_specialization_inconsistent_storage_class : Error<
|
||||
"'%select{none|extern|static|__private_extern__|auto|register}0'">;
|
||||
def err_dependent_function_template_spec_no_match : Error<
|
||||
"no candidate function template was found for dependent"
|
||||
" friend function template specialization">;
|
||||
" %select{member|friend}0 function template specialization">;
|
||||
def note_dependent_function_template_spec_discard_reason : Note<
|
||||
"candidate ignored: %select{not a function template"
|
||||
"|not a member of the enclosing namespace;"
|
||||
" did you mean to explicitly qualify the specialization?}0">;
|
||||
"candidate ignored: %select{not a function template|"
|
||||
"not a member of the enclosing %select{class template|"
|
||||
"namespace; did you mean to explicitly qualify the specialization?}1}0">;
|
||||
|
||||
// C++ class template specializations and out-of-line definitions
|
||||
def err_template_spec_needs_header : Error<
|
||||
|
@ -8451,9 +8451,9 @@ public:
|
||||
SourceLocation PrevPtOfInstantiation,
|
||||
bool &SuppressNew);
|
||||
|
||||
bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
const TemplateArgumentListInfo &ExplicitTemplateArgs,
|
||||
LookupResult &Previous);
|
||||
bool CheckDependentFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous);
|
||||
|
||||
bool CheckFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
|
@ -630,8 +630,6 @@ enum class TemplateSubstitutionKind : char {
|
||||
// A few supplemental visitor functions.
|
||||
Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
|
||||
TemplateParameterList *TemplateParams,
|
||||
std::optional<const ASTTemplateArgumentListInfo *>
|
||||
ClassScopeSpecializationArgs = std::nullopt,
|
||||
RewriteKind RK = RewriteKind::None);
|
||||
Decl *VisitFunctionDecl(FunctionDecl *D,
|
||||
TemplateParameterList *TemplateParams,
|
||||
|
@ -1475,10 +1475,6 @@ enum DeclCode {
|
||||
/// template template parameter pack.
|
||||
DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
|
||||
|
||||
/// A ClassScopeFunctionSpecializationDecl record a class scope
|
||||
/// function specialization. (Microsoft extension).
|
||||
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
|
||||
|
||||
/// An ImportDecl recording a module import.
|
||||
DECL_IMPORT,
|
||||
|
||||
|
@ -155,6 +155,8 @@ public:
|
||||
/// Reads a TemplateArgumentLoc, advancing Idx.
|
||||
TemplateArgumentLoc readTemplateArgumentLoc();
|
||||
|
||||
void readTemplateArgumentListInfo(TemplateArgumentListInfo &Result);
|
||||
|
||||
const ASTTemplateArgumentListInfo*
|
||||
readASTTemplateArgumentListInfo();
|
||||
|
||||
|
@ -3342,27 +3342,25 @@ Error ASTNodeImporter::ImportTemplateInformation(
|
||||
|
||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
|
||||
auto *FromInfo = FromFD->getDependentSpecializationInfo();
|
||||
UnresolvedSet<8> TemplDecls;
|
||||
unsigned NumTemplates = FromInfo->getNumTemplates();
|
||||
for (unsigned I = 0; I < NumTemplates; I++) {
|
||||
if (Expected<FunctionTemplateDecl *> ToFTDOrErr =
|
||||
import(FromInfo->getTemplate(I)))
|
||||
TemplDecls.addDecl(*ToFTDOrErr);
|
||||
UnresolvedSet<8> Candidates;
|
||||
for (FunctionTemplateDecl *FTD : FromInfo->getCandidates()) {
|
||||
if (Expected<FunctionTemplateDecl *> ToFTDOrErr = import(FTD))
|
||||
Candidates.addDecl(*ToFTDOrErr);
|
||||
else
|
||||
return ToFTDOrErr.takeError();
|
||||
}
|
||||
|
||||
// Import TemplateArgumentListInfo.
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(),
|
||||
llvm::ArrayRef(FromInfo->getTemplateArgs(),
|
||||
FromInfo->getNumTemplateArgs()),
|
||||
ToTAInfo))
|
||||
return Err;
|
||||
const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten;
|
||||
if (FromTAArgsAsWritten)
|
||||
if (Error Err =
|
||||
ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
|
||||
return Err;
|
||||
|
||||
ToFD->setDependentTemplateSpecialization(Importer.getToContext(),
|
||||
TemplDecls, ToTAInfo);
|
||||
ToFD->setDependentTemplateSpecialization(
|
||||
Importer.getToContext(), Candidates,
|
||||
FromTAArgsAsWritten ? &ToTAInfo : nullptr);
|
||||
return Error::success();
|
||||
}
|
||||
}
|
||||
|
@ -3975,6 +3975,12 @@ void FunctionDecl::setDescribedFunctionTemplate(
|
||||
TemplateOrSpecialization = Template;
|
||||
}
|
||||
|
||||
bool FunctionDecl::isFunctionTemplateSpecialization() const {
|
||||
return TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>() ||
|
||||
TemplateOrSpecialization
|
||||
.is<DependentFunctionTemplateSpecializationInfo *>();
|
||||
}
|
||||
|
||||
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
|
||||
assert(TemplateOrSpecialization.isNull() &&
|
||||
"Function is already a specialization");
|
||||
@ -4109,6 +4115,11 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
|
||||
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
|
||||
return Info->TemplateArgumentsAsWritten;
|
||||
}
|
||||
if (DependentFunctionTemplateSpecializationInfo *Info =
|
||||
TemplateOrSpecialization
|
||||
.dyn_cast<DependentFunctionTemplateSpecializationInfo *>()) {
|
||||
return Info->TemplateArgumentsAsWritten;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -4137,10 +4148,9 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
|
||||
Template->addSpecialization(Info, InsertPos);
|
||||
}
|
||||
|
||||
void
|
||||
FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
|
||||
const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo &TemplateArgs) {
|
||||
void FunctionDecl::setDependentTemplateSpecialization(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
assert(TemplateOrSpecialization.isNull());
|
||||
DependentFunctionTemplateSpecializationInfo *Info =
|
||||
DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
|
||||
@ -4156,28 +4166,26 @@ FunctionDecl::getDependentSpecializationInfo() const {
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo *
|
||||
DependentFunctionTemplateSpecializationInfo::Create(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Ts,
|
||||
const TemplateArgumentListInfo &TArgs) {
|
||||
void *Buffer = Context.Allocate(
|
||||
totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>(
|
||||
TArgs.size(), Ts.size()));
|
||||
return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs);
|
||||
ASTContext &Context, const UnresolvedSetImpl &Candidates,
|
||||
const TemplateArgumentListInfo *TArgs) {
|
||||
const auto *TArgsWritten =
|
||||
TArgs ? ASTTemplateArgumentListInfo::Create(Context, *TArgs) : nullptr;
|
||||
return new (Context.Allocate(
|
||||
totalSizeToAlloc<FunctionTemplateDecl *>(Candidates.size())))
|
||||
DependentFunctionTemplateSpecializationInfo(Candidates, TArgsWritten);
|
||||
}
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo::
|
||||
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
|
||||
const TemplateArgumentListInfo &TArgs)
|
||||
: AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
|
||||
NumTemplates = Ts.size();
|
||||
NumArgs = TArgs.size();
|
||||
|
||||
FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>();
|
||||
for (unsigned I = 0, E = Ts.size(); I != E; ++I)
|
||||
TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
|
||||
|
||||
TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>();
|
||||
for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
|
||||
new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Candidates,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsWritten)
|
||||
: TemplateArgumentsAsWritten(TemplateArgsWritten),
|
||||
NumCandidates(Candidates.size()) {
|
||||
std::transform(Candidates.begin(), Candidates.end(),
|
||||
getTrailingObjects<FunctionTemplateDecl *>(),
|
||||
[](NamedDecl *ND) {
|
||||
return cast<FunctionTemplateDecl>(ND->getUnderlyingDecl());
|
||||
});
|
||||
}
|
||||
|
||||
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
|
||||
@ -4192,6 +4200,13 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
|
||||
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
||||
return MSInfo->getTemplateSpecializationKind();
|
||||
|
||||
// A dependent function template specialization is an explicit specialization,
|
||||
// except when it's a friend declaration.
|
||||
if (TemplateOrSpecialization
|
||||
.is<DependentFunctionTemplateSpecializationInfo *>() &&
|
||||
getFriendObjectKind() == FOK_None)
|
||||
return TSK_ExplicitSpecialization;
|
||||
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
@ -4206,6 +4221,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
|
||||
// template<> void f<int>() {}
|
||||
// };
|
||||
//
|
||||
// Within the templated CXXRecordDecl, A<T>::f<int> is a dependent function
|
||||
// template specialization; both getTemplateSpecializationKind() and
|
||||
// getTemplateSpecializationKindForInstantiation() will return
|
||||
// TSK_ExplicitSpecialization.
|
||||
//
|
||||
// For A<int>::f<int>():
|
||||
// * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
|
||||
// * getTemplateSpecializationKindForInstantiation() will return
|
||||
@ -4226,6 +4246,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
|
||||
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
|
||||
return MSInfo->getTemplateSpecializationKind();
|
||||
|
||||
if (TemplateOrSpecialization
|
||||
.is<DependentFunctionTemplateSpecializationInfo *>() &&
|
||||
getFriendObjectKind() == FOK_None)
|
||||
return TSK_ExplicitSpecialization;
|
||||
|
||||
return TSK_Undeclared;
|
||||
}
|
||||
|
||||
|
@ -936,7 +936,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case BuiltinTemplate:
|
||||
case ClassTemplateSpecialization:
|
||||
case ClassTemplatePartialSpecialization:
|
||||
case ClassScopeFunctionSpecialization:
|
||||
case VarTemplateSpecialization:
|
||||
case VarTemplatePartialSpecialization:
|
||||
case ObjCImplementation:
|
||||
@ -1077,9 +1076,7 @@ bool Decl::AccessDeclContextCheck() const {
|
||||
isa<ParmVarDecl>(this) ||
|
||||
// FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
|
||||
// AS_none as access specifier.
|
||||
isa<CXXRecordDecl>(this) ||
|
||||
isa<ClassScopeFunctionSpecializationDecl>(this) ||
|
||||
isa<LifetimeExtendedTemporaryDecl>(this))
|
||||
isa<CXXRecordDecl>(this) || isa<LifetimeExtendedTemporaryDecl>(this))
|
||||
return true;
|
||||
|
||||
assert(Access != AS_none &&
|
||||
|
@ -1195,19 +1195,6 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
|
||||
return CommonPtr;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ClassScopeFunctionSpecializationDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ClassScopeFunctionSpecializationDecl::anchor() {}
|
||||
|
||||
ClassScopeFunctionSpecializationDecl *
|
||||
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
|
||||
unsigned ID) {
|
||||
return new (C, ID) ClassScopeFunctionSpecializationDecl(
|
||||
nullptr, SourceLocation(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// VarTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -658,6 +658,10 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
|
||||
if (F->isFunctionTemplateSpecialization()) {
|
||||
if (!isa<CXXMethodDecl>(DC)) return;
|
||||
if (DC->getLexicalParent()->isFileContext()) return;
|
||||
// Skip class scope explicit function template specializations,
|
||||
// as they have not yet been instantiated.
|
||||
if (F->getDependentSpecializationInfo())
|
||||
return;
|
||||
// Inline method specializations are the only supported
|
||||
// specialization for now.
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||
case Decl::FriendTemplate:
|
||||
case Decl::Block:
|
||||
case Decl::Captured:
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::UsingShadow:
|
||||
case Decl::ConstructorUsingShadow:
|
||||
case Decl::ObjCTypeParam:
|
||||
|
@ -346,7 +346,6 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
|
||||
}
|
||||
break;
|
||||
case Decl::ClassTemplatePartialSpecialization:
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::ClassTemplateSpecialization:
|
||||
case Decl::CXXRecord:
|
||||
case Decl::Enum:
|
||||
|
@ -9775,7 +9775,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
bool isMemberSpecialization = false;
|
||||
bool isFunctionTemplateSpecialization = false;
|
||||
|
||||
bool isDependentClassScopeExplicitSpecialization = false;
|
||||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
|
||||
@ -10415,12 +10414,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
|
||||
|
||||
HasExplicitTemplateArgs = false;
|
||||
} else {
|
||||
assert((isFunctionTemplateSpecialization ||
|
||||
D.getDeclSpec().isFriendSpecified()) &&
|
||||
"should have a 'template<>' for this decl");
|
||||
} else if (isFriend) {
|
||||
// "friend void foo<>(int);" is an implicit specialization decl.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
} else {
|
||||
assert(isFunctionTemplateSpecialization &&
|
||||
"should have a 'template<>' for this decl");
|
||||
}
|
||||
} else if (isFriend && isFunctionTemplateSpecialization) {
|
||||
// This combination is only possible in a recovery case; the user
|
||||
@ -10443,32 +10442,54 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
if (getLangOpts().CUDA && !isFunctionTemplateSpecialization)
|
||||
maybeAddCUDAHostDeviceAttrs(NewFD, Previous);
|
||||
|
||||
// If it's a friend (and only if it's a friend), it's possible
|
||||
// that either the specialized function type or the specialized
|
||||
// template is dependent, and therefore matching will fail. In
|
||||
// this case, don't check the specialization yet.
|
||||
if (isFunctionTemplateSpecialization && isFriend &&
|
||||
(NewFD->getType()->isDependentType() || DC->isDependentContext() ||
|
||||
TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
|
||||
TemplateArgs.arguments()))) {
|
||||
assert(HasExplicitTemplateArgs &&
|
||||
"friend function specialization without template args");
|
||||
if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
|
||||
Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
} else if (isFunctionTemplateSpecialization) {
|
||||
if (CurContext->isDependentContext() && CurContext->isRecord()
|
||||
&& !isFriend) {
|
||||
isDependentClassScopeExplicitSpecialization = true;
|
||||
} else if (!NewFD->isInvalidDecl() &&
|
||||
CheckFunctionTemplateSpecialization(
|
||||
NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
|
||||
Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
// Handle explict specializations of function templates
|
||||
// and friend function declarations with an explicit
|
||||
// template argument list.
|
||||
if (isFunctionTemplateSpecialization) {
|
||||
bool isDependentSpecialization = false;
|
||||
if (isFriend) {
|
||||
// For friend function specializations, this is a dependent
|
||||
// specialization if its semantic context is dependent, its
|
||||
// type is dependent, or if its template-id is dependent.
|
||||
isDependentSpecialization =
|
||||
DC->isDependentContext() || NewFD->getType()->isDependentType() ||
|
||||
(HasExplicitTemplateArgs &&
|
||||
TemplateSpecializationType::
|
||||
anyInstantiationDependentTemplateArguments(
|
||||
TemplateArgs.arguments()));
|
||||
assert(!isDependentSpecialization ||
|
||||
(HasExplicitTemplateArgs == isDependentSpecialization) &&
|
||||
"dependent friend function specialization without template "
|
||||
"args");
|
||||
} else {
|
||||
// For class-scope explicit specializations of function templates,
|
||||
// if the lexical context is dependent, then the specialization
|
||||
// is dependent.
|
||||
isDependentSpecialization =
|
||||
CurContext->isRecord() && CurContext->isDependentContext();
|
||||
}
|
||||
|
||||
TemplateArgumentListInfo *ExplicitTemplateArgs =
|
||||
HasExplicitTemplateArgs ? &TemplateArgs : nullptr;
|
||||
if (isDependentSpecialization) {
|
||||
// If it's a dependent specialization, it may not be possible
|
||||
// to determine the primary template (for explicit specializations)
|
||||
// or befriended declaration (for friends) until the enclosing
|
||||
// template is instantiated. In such cases, we store the declarations
|
||||
// found by name lookup and defer resolution until instantiation.
|
||||
if (CheckDependentFunctionTemplateSpecialization(
|
||||
NewFD, ExplicitTemplateArgs, Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
} else if (!NewFD->isInvalidDecl()) {
|
||||
if (CheckFunctionTemplateSpecialization(NewFD, ExplicitTemplateArgs,
|
||||
Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
}
|
||||
|
||||
// C++ [dcl.stc]p1:
|
||||
// A storage-class-specifier shall not be specified in an explicit
|
||||
// specialization (14.7.3)
|
||||
// FIXME: We should be checking this for dependent specializations.
|
||||
FunctionTemplateSpecializationInfo *Info =
|
||||
NewFD->getTemplateSpecializationInfo();
|
||||
if (Info && SC != SC_None) {
|
||||
@ -10491,21 +10512,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
}
|
||||
|
||||
// Perform semantic checking on the function declaration.
|
||||
if (!isDependentClassScopeExplicitSpecialization) {
|
||||
if (!NewFD->isInvalidDecl() && NewFD->isMain())
|
||||
CheckMain(NewFD, D.getDeclSpec());
|
||||
if (!NewFD->isInvalidDecl() && NewFD->isMain())
|
||||
CheckMain(NewFD, D.getDeclSpec());
|
||||
|
||||
if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
|
||||
CheckMSVCRTEntryPoint(NewFD);
|
||||
if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
|
||||
CheckMSVCRTEntryPoint(NewFD);
|
||||
|
||||
if (!NewFD->isInvalidDecl())
|
||||
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
|
||||
isMemberSpecialization,
|
||||
D.isFunctionDefinition()));
|
||||
else if (!Previous.empty())
|
||||
// Recover gracefully from an invalid redeclaration.
|
||||
D.setRedeclaration(true);
|
||||
}
|
||||
if (!NewFD->isInvalidDecl())
|
||||
D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
|
||||
isMemberSpecialization,
|
||||
D.isFunctionDefinition()));
|
||||
else if (!Previous.empty())
|
||||
// Recover gracefully from an invalid redeclaration.
|
||||
D.setRedeclaration(true);
|
||||
|
||||
assert((NewFD->isInvalidDecl() || NewFD->isMultiVersion() ||
|
||||
!D.isRedeclaration() ||
|
||||
@ -10817,19 +10836,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
}
|
||||
}
|
||||
|
||||
// Here we have an function template explicit specialization at class scope.
|
||||
// The actual specialization will be postponed to template instatiation
|
||||
// time via the ClassScopeFunctionSpecializationDecl node.
|
||||
if (isDependentClassScopeExplicitSpecialization) {
|
||||
ClassScopeFunctionSpecializationDecl *NewSpec =
|
||||
ClassScopeFunctionSpecializationDecl::Create(
|
||||
Context, CurContext, NewFD->getLocation(),
|
||||
cast<CXXMethodDecl>(NewFD),
|
||||
HasExplicitTemplateArgs, TemplateArgs);
|
||||
CurContext->addDecl(NewSpec);
|
||||
AddToScope = false;
|
||||
}
|
||||
|
||||
// Diagnose availability attributes. Availability cannot be used on functions
|
||||
// that are run during load/unload.
|
||||
if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) {
|
||||
|
@ -9334,10 +9334,9 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
||||
///
|
||||
/// There really isn't any useful analysis we can do here, so we
|
||||
/// just store the information.
|
||||
bool
|
||||
Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
const TemplateArgumentListInfo &ExplicitTemplateArgs,
|
||||
LookupResult &Previous) {
|
||||
bool Sema::CheckDependentFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous) {
|
||||
// Remove anything from Previous that isn't a function template in
|
||||
// the correct context.
|
||||
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
|
||||
@ -9361,13 +9360,14 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
|
||||
}
|
||||
F.done();
|
||||
|
||||
bool IsFriend = FD->getFriendObjectKind() != Decl::FOK_None;
|
||||
if (Previous.empty()) {
|
||||
Diag(FD->getLocation(),
|
||||
diag::err_dependent_function_template_spec_no_match);
|
||||
Diag(FD->getLocation(), diag::err_dependent_function_template_spec_no_match)
|
||||
<< IsFriend;
|
||||
for (auto &P : DiscardedCandidates)
|
||||
Diag(P.second->getLocation(),
|
||||
diag::note_dependent_function_template_spec_discard_reason)
|
||||
<< P.first;
|
||||
<< P.first << IsFriend;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2247,42 +2247,46 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
||||
D->isLocalExternDecl() ? Sema::ForExternalRedeclaration
|
||||
: SemaRef.forRedeclarationInCurContext());
|
||||
|
||||
if (DependentFunctionTemplateSpecializationInfo *Info
|
||||
= D->getDependentSpecializationInfo()) {
|
||||
assert(isFriend && "non-friend has dependent specialization info?");
|
||||
if (DependentFunctionTemplateSpecializationInfo *DFTSI =
|
||||
D->getDependentSpecializationInfo()) {
|
||||
assert(isFriend && "dependent specialization info on "
|
||||
"non-member non-friend function?");
|
||||
|
||||
// Instantiate the explicit template arguments.
|
||||
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
|
||||
Info->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
// Map the candidate templates to their instantiations.
|
||||
for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
|
||||
Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
|
||||
Info->getTemplate(I),
|
||||
TemplateArgs);
|
||||
if (!Temp) return nullptr;
|
||||
|
||||
Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
|
||||
TemplateArgumentListInfo ExplicitArgs;
|
||||
if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) {
|
||||
ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc());
|
||||
ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Function,
|
||||
&ExplicitArgs,
|
||||
Previous))
|
||||
// Map the candidates for the primary template to their instantiations.
|
||||
for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) {
|
||||
if (NamedDecl *ND =
|
||||
SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs))
|
||||
Previous.addDecl(ND);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(
|
||||
Function,
|
||||
DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
|
||||
Previous))
|
||||
Function->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
} else if (const ASTTemplateArgumentListInfo *Info =
|
||||
} else if (const ASTTemplateArgumentListInfo *ArgsWritten =
|
||||
D->getTemplateSpecializationArgsAsWritten()) {
|
||||
// The name of this function was written as a template-id.
|
||||
SemaRef.LookupQualifiedName(Previous, DC);
|
||||
|
||||
// Instantiate the explicit template arguments.
|
||||
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
|
||||
Info->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
|
||||
TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(),
|
||||
ArgsWritten->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
@ -2404,8 +2408,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
||||
CXXMethodDecl *D, TemplateParameterList *TemplateParams,
|
||||
std::optional<const ASTTemplateArgumentListInfo *>
|
||||
ClassScopeSpecializationArgs,
|
||||
RewriteKind FunctionRewriteKind) {
|
||||
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
||||
if (FunctionTemplate && !TemplateParams) {
|
||||
@ -2635,41 +2637,41 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
||||
|
||||
// If the name of this function was written as a template-id, instantiate
|
||||
// the explicit template arguments.
|
||||
if (DependentFunctionTemplateSpecializationInfo *Info
|
||||
= D->getDependentSpecializationInfo()) {
|
||||
assert(isFriend && "non-friend has dependent specialization info?");
|
||||
|
||||
if (DependentFunctionTemplateSpecializationInfo *DFTSI =
|
||||
D->getDependentSpecializationInfo()) {
|
||||
// Instantiate the explicit template arguments.
|
||||
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
|
||||
Info->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
// Map the candidate templates to their instantiations.
|
||||
for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
|
||||
Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
|
||||
Info->getTemplate(I),
|
||||
TemplateArgs);
|
||||
if (!Temp) return nullptr;
|
||||
|
||||
Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
|
||||
TemplateArgumentListInfo ExplicitArgs;
|
||||
if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) {
|
||||
ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc());
|
||||
ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Method,
|
||||
&ExplicitArgs,
|
||||
Previous))
|
||||
// Map the candidates for the primary template to their instantiations.
|
||||
for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) {
|
||||
if (NamedDecl *ND =
|
||||
SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs))
|
||||
Previous.addDecl(ND);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(
|
||||
Method, DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
|
||||
Previous))
|
||||
Method->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
} else if (const ASTTemplateArgumentListInfo *Info =
|
||||
ClassScopeSpecializationArgs.value_or(
|
||||
D->getTemplateSpecializationArgsAsWritten())) {
|
||||
} else if (const ASTTemplateArgumentListInfo *ArgsWritten =
|
||||
D->getTemplateSpecializationArgsAsWritten()) {
|
||||
SemaRef.LookupQualifiedName(Previous, DC);
|
||||
|
||||
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
|
||||
Info->getRAngleLoc());
|
||||
if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
|
||||
TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(),
|
||||
ArgsWritten->getRAngleLoc());
|
||||
|
||||
if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
|
||||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
@ -2678,14 +2680,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
||||
Previous))
|
||||
Method->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
} else if (ClassScopeSpecializationArgs) {
|
||||
// Class-scope explicit specialization written without explicit template
|
||||
// arguments.
|
||||
SemaRef.LookupQualifiedName(Previous, DC);
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Method, nullptr, Previous))
|
||||
Method->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
} else if (!FunctionTemplate || TemplateParams || isFriend) {
|
||||
SemaRef.LookupQualifiedName(Previous, Record);
|
||||
@ -3510,13 +3504,6 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
|
||||
return NewD;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *Decl) {
|
||||
CXXMethodDecl *OldFD = Decl->getSpecialization();
|
||||
return cast_or_null<CXXMethodDecl>(
|
||||
VisitCXXMethodDecl(OldFD, nullptr, Decl->getTemplateArgsAsWritten()));
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
|
||||
OMPThreadPrivateDecl *D) {
|
||||
SmallVector<Expr *, 5> Vars;
|
||||
@ -4094,14 +4081,14 @@ FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
|
||||
Decl *R;
|
||||
if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) {
|
||||
R = Instantiator.VisitCXXMethodDecl(
|
||||
MD, nullptr, std::nullopt,
|
||||
MD, /*TemplateParams=*/nullptr,
|
||||
TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual);
|
||||
} else {
|
||||
assert(Spaceship->getFriendObjectKind() &&
|
||||
"defaulted spaceship is neither a member nor a friend");
|
||||
|
||||
R = Instantiator.VisitFunctionDecl(
|
||||
Spaceship, nullptr,
|
||||
Spaceship, /*TemplateParams=*/nullptr,
|
||||
TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual);
|
||||
if (!R)
|
||||
return nullptr;
|
||||
|
@ -424,7 +424,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
||||
case Decl::StaticAssert:
|
||||
case Decl::Block:
|
||||
case Decl::Captured:
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::Import:
|
||||
case Decl::OMPThreadPrivate:
|
||||
case Decl::OMPAllocate:
|
||||
|
@ -7435,15 +7435,20 @@ TemplateArgumentLoc ASTRecordReader::readTemplateArgumentLoc() {
|
||||
return TemplateArgumentLoc(Arg, readTemplateArgumentLocInfo(Arg.getKind()));
|
||||
}
|
||||
|
||||
void ASTRecordReader::readTemplateArgumentListInfo(
|
||||
TemplateArgumentListInfo &Result) {
|
||||
Result.setLAngleLoc(readSourceLocation());
|
||||
Result.setRAngleLoc(readSourceLocation());
|
||||
unsigned NumArgsAsWritten = readInt();
|
||||
for (unsigned i = 0; i != NumArgsAsWritten; ++i)
|
||||
Result.addArgument(readTemplateArgumentLoc());
|
||||
}
|
||||
|
||||
const ASTTemplateArgumentListInfo *
|
||||
ASTRecordReader::readASTTemplateArgumentListInfo() {
|
||||
SourceLocation LAngleLoc = readSourceLocation();
|
||||
SourceLocation RAngleLoc = readSourceLocation();
|
||||
unsigned NumArgsAsWritten = readInt();
|
||||
TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
|
||||
for (unsigned i = 0; i != NumArgsAsWritten; ++i)
|
||||
TemplArgsInfo.addArgument(readTemplateArgumentLoc());
|
||||
return ASTTemplateArgumentListInfo::Create(getContext(), TemplArgsInfo);
|
||||
TemplateArgumentListInfo Result;
|
||||
readTemplateArgumentListInfo(Result);
|
||||
return ASTTemplateArgumentListInfo::Create(getContext(), Result);
|
||||
}
|
||||
|
||||
Decl *ASTReader::GetExternalDecl(uint32_t ID) {
|
||||
|
@ -358,9 +358,7 @@ namespace clang {
|
||||
}
|
||||
|
||||
void VisitClassTemplatePartialSpecializationDecl(
|
||||
ClassTemplatePartialSpecializationDecl *D);
|
||||
void VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *D);
|
||||
ClassTemplatePartialSpecializationDecl *D);
|
||||
RedeclarableResult
|
||||
VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
|
||||
|
||||
@ -950,27 +948,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
|
||||
|
||||
// Template args as written.
|
||||
SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
bool HasTemplateArgumentsAsWritten = Record.readInt();
|
||||
if (HasTemplateArgumentsAsWritten) {
|
||||
unsigned NumTemplateArgLocs = Record.readInt();
|
||||
TemplArgLocs.reserve(NumTemplateArgLocs);
|
||||
for (unsigned i = 0; i != NumTemplateArgLocs; ++i)
|
||||
TemplArgLocs.push_back(Record.readTemplateArgumentLoc());
|
||||
|
||||
LAngleLoc = readSourceLocation();
|
||||
RAngleLoc = readSourceLocation();
|
||||
}
|
||||
TemplateArgumentListInfo TemplArgsWritten;
|
||||
bool HasTemplateArgumentsAsWritten = Record.readBool();
|
||||
if (HasTemplateArgumentsAsWritten)
|
||||
Record.readTemplateArgumentListInfo(TemplArgsWritten);
|
||||
|
||||
SourceLocation POI = readSourceLocation();
|
||||
|
||||
ASTContext &C = Reader.getContext();
|
||||
TemplateArgumentList *TemplArgList
|
||||
= TemplateArgumentList::CreateCopy(C, TemplArgs);
|
||||
TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
|
||||
for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i)
|
||||
TemplArgsInfo.addArgument(TemplArgLocs[i]);
|
||||
TemplateArgumentList *TemplArgList =
|
||||
TemplateArgumentList::CreateCopy(C, TemplArgs);
|
||||
|
||||
MemberSpecializationInfo *MSInfo = nullptr;
|
||||
if (Record.readInt()) {
|
||||
@ -985,7 +972,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
FunctionTemplateSpecializationInfo *FTInfo =
|
||||
FunctionTemplateSpecializationInfo::Create(
|
||||
C, FD, Template, TSK, TemplArgList,
|
||||
HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI,
|
||||
HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr, POI,
|
||||
MSInfo);
|
||||
FD->TemplateOrSpecialization = FTInfo;
|
||||
|
||||
@ -1016,21 +1003,20 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
}
|
||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
|
||||
// Templates.
|
||||
UnresolvedSet<8> TemplDecls;
|
||||
unsigned NumTemplates = Record.readInt();
|
||||
while (NumTemplates--)
|
||||
TemplDecls.addDecl(readDeclAs<NamedDecl>());
|
||||
UnresolvedSet<8> Candidates;
|
||||
unsigned NumCandidates = Record.readInt();
|
||||
while (NumCandidates--)
|
||||
Candidates.addDecl(readDeclAs<NamedDecl>());
|
||||
|
||||
// Templates args.
|
||||
TemplateArgumentListInfo TemplArgs;
|
||||
unsigned NumArgs = Record.readInt();
|
||||
while (NumArgs--)
|
||||
TemplArgs.addArgument(Record.readTemplateArgumentLoc());
|
||||
TemplArgs.setLAngleLoc(readSourceLocation());
|
||||
TemplArgs.setRAngleLoc(readSourceLocation());
|
||||
TemplateArgumentListInfo TemplArgsWritten;
|
||||
bool HasTemplateArgumentsAsWritten = Record.readBool();
|
||||
if (HasTemplateArgumentsAsWritten)
|
||||
Record.readTemplateArgumentListInfo(TemplArgsWritten);
|
||||
|
||||
FD->setDependentTemplateSpecialization(Reader.getContext(),
|
||||
TemplDecls, TemplArgs);
|
||||
FD->setDependentTemplateSpecialization(
|
||||
Reader.getContext(), Candidates,
|
||||
HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr);
|
||||
// These are not merged; we don't need to merge redeclarations of dependent
|
||||
// template friends.
|
||||
break;
|
||||
@ -2525,14 +2511,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
|
||||
}
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *D) {
|
||||
VisitDecl(D);
|
||||
D->Specialization = readDeclAs<CXXMethodDecl>();
|
||||
if (Record.readInt())
|
||||
D->TemplateArgs = Record.readASTTemplateArgumentListInfo();
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
@ -3881,9 +3859,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
||||
case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
|
||||
D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
|
||||
D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
case DECL_FUNCTION_TEMPLATE:
|
||||
D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
|
@ -1029,7 +1029,6 @@ void ASTWriter::WriteBlockInfoBlock() {
|
||||
RECORD(DECL_INDIRECTFIELD);
|
||||
RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);
|
||||
RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK);
|
||||
RECORD(DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION);
|
||||
RECORD(DECL_IMPORT);
|
||||
RECORD(DECL_OMP_THREADPRIVATE);
|
||||
RECORD(DECL_EMPTY);
|
||||
|
@ -81,8 +81,6 @@ namespace clang {
|
||||
void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
|
||||
void VisitVarTemplatePartialSpecializationDecl(
|
||||
VarTemplatePartialSpecializationDecl *D);
|
||||
void VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *D);
|
||||
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
|
||||
void VisitValueDecl(ValueDecl *D);
|
||||
void VisitEnumConstantDecl(EnumConstantDecl *D);
|
||||
@ -617,15 +615,9 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
|
||||
// Template args as written.
|
||||
Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
|
||||
if (FTSInfo->TemplateArgumentsAsWritten) {
|
||||
Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs);
|
||||
for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs;
|
||||
i!=e; ++i)
|
||||
Record.AddTemplateArgumentLoc(
|
||||
(*FTSInfo->TemplateArgumentsAsWritten)[i]);
|
||||
Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc);
|
||||
Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc);
|
||||
}
|
||||
if (FTSInfo->TemplateArgumentsAsWritten)
|
||||
Record.AddASTTemplateArgumentListInfo(
|
||||
FTSInfo->TemplateArgumentsAsWritten);
|
||||
|
||||
Record.AddSourceLocation(FTSInfo->getPointOfInstantiation());
|
||||
|
||||
@ -650,17 +642,16 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
DependentFunctionTemplateSpecializationInfo *
|
||||
DFTSInfo = D->getDependentSpecializationInfo();
|
||||
|
||||
// Templates.
|
||||
Record.push_back(DFTSInfo->getNumTemplates());
|
||||
for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i)
|
||||
Record.AddDeclRef(DFTSInfo->getTemplate(i));
|
||||
// Candidates.
|
||||
Record.push_back(DFTSInfo->getCandidates().size());
|
||||
for (FunctionTemplateDecl *FTD : DFTSInfo->getCandidates())
|
||||
Record.AddDeclRef(FTD);
|
||||
|
||||
// Templates args.
|
||||
Record.push_back(DFTSInfo->getNumTemplateArgs());
|
||||
for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i)
|
||||
Record.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i));
|
||||
Record.AddSourceLocation(DFTSInfo->getLAngleLoc());
|
||||
Record.AddSourceLocation(DFTSInfo->getRAngleLoc());
|
||||
Record.push_back(DFTSInfo->TemplateArgumentsAsWritten != nullptr);
|
||||
if (DFTSInfo->TemplateArgumentsAsWritten)
|
||||
Record.AddASTTemplateArgumentListInfo(
|
||||
DFTSInfo->TemplateArgumentsAsWritten);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1739,17 +1730,6 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
|
||||
Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
|
||||
ClassScopeFunctionSpecializationDecl *D) {
|
||||
VisitDecl(D);
|
||||
Record.AddDeclRef(D->getSpecialization());
|
||||
Record.push_back(D->hasExplicitTemplateArgs());
|
||||
if (D->hasExplicitTemplateArgs())
|
||||
Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
|
||||
Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION;
|
||||
}
|
||||
|
||||
|
||||
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
|
@ -202,7 +202,7 @@ static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD) {
|
||||
static QualType getPointerTypeFromTemplateArg(const CallEvent &Call,
|
||||
CheckerContext &C) {
|
||||
const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
|
||||
if (!FD || !FD->isFunctionTemplateSpecialization())
|
||||
if (!FD || !FD->getPrimaryTemplate())
|
||||
return {};
|
||||
const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
|
||||
if (TemplateArgs.size() == 0)
|
||||
|
@ -645,11 +645,16 @@ class TestClassScopeFunctionSpecialization {
|
||||
template<class U> void foo(U a) { }
|
||||
template<> void foo<int>(int a) { }
|
||||
};
|
||||
// CHECK: ClassScopeFunctionSpecializationDecl
|
||||
// CHECK-NEXT: CXXMethod{{.*}} foo 'void (int)'
|
||||
// CHECK: FunctionTemplateDecl{{.*}} foo
|
||||
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} referenced class depth 1 index 0 U
|
||||
// CHECK-NEXT: CXXMethodDecl{{.*}} foo 'void (U)' implicit-inline
|
||||
// CHECK-NEXT: ParmVarDecl
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: CXXMethodDecl{{.*}} foo 'void (int)' explicit_specialization implicit-inline
|
||||
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
|
||||
// CHECK-NEXT: BuiltinType{{.*}} 'int'
|
||||
// CHECK-NEXT: ParmVarDecl
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
|
||||
namespace TestTemplateTypeParmDecl {
|
||||
template<typename ... T, class U = int> void foo();
|
||||
|
@ -111,6 +111,11 @@ namespace dr727 { // dr727: partial
|
||||
|
||||
template<typename T> struct C<T*> {};
|
||||
template<typename T> static const int N<T*>;
|
||||
|
||||
template<typename>
|
||||
struct E {
|
||||
template<> void f<void>() {} // expected-error {{no candidate function template}}
|
||||
};
|
||||
};
|
||||
|
||||
void d(D<int> di) {
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
virtual ~HasDestructor() = 0;
|
||||
};
|
||||
|
||||
int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
|
||||
int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
|
||||
// the code below should probably instantiate by itself.
|
||||
int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
|
||||
|
||||
@ -94,7 +94,7 @@ struct X0 : X0Base {
|
||||
|
||||
template<typename U>
|
||||
struct X1 : X0<U> {
|
||||
int &f2() {
|
||||
int &f2() {
|
||||
return X0Base::f();
|
||||
}
|
||||
};
|
||||
@ -129,19 +129,19 @@ namespace test1 {
|
||||
}
|
||||
|
||||
namespace PR6947 {
|
||||
template< class T >
|
||||
template< class T >
|
||||
struct X {
|
||||
int f0( )
|
||||
int f0( )
|
||||
{
|
||||
typedef void ( X::*impl_fun_ptr )( );
|
||||
impl_fun_ptr pImpl = &X::template
|
||||
f0_impl1<int>;
|
||||
}
|
||||
private:
|
||||
private:
|
||||
int f1() {
|
||||
}
|
||||
template< class Processor>
|
||||
void f0_impl1( )
|
||||
template< class Processor>
|
||||
void f0_impl1( )
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -154,7 +154,7 @@ namespace PR6947 {
|
||||
}
|
||||
|
||||
namespace PR7022 {
|
||||
template <typename >
|
||||
template <typename >
|
||||
struct X1
|
||||
{
|
||||
typedef int state_t( );
|
||||
@ -185,13 +185,12 @@ namespace SameSignatureAfterInstantiation {
|
||||
|
||||
namespace PR22040 {
|
||||
template <typename T> struct Foobar {
|
||||
template <> void bazqux(typename T::type) {} // expected-error 2{{cannot be used prior to '::' because it has no members}}
|
||||
template <> void bazqux(typename T::type) {} // expected-error {{no candidate function template was found for dependent member function template specialization}}
|
||||
};
|
||||
|
||||
void test() {
|
||||
// FIXME: we should suppress the "no member" errors
|
||||
Foobar<void>::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }}
|
||||
Foobar<int>::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }}
|
||||
Foobar<void>::bazqux();
|
||||
Foobar<int>::bazqux();
|
||||
Foobar<int>::bazqux(3); // expected-error{{no member named 'bazqux' in }}
|
||||
}
|
||||
}
|
||||
|
@ -6848,7 +6848,6 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||
case Decl::Captured:
|
||||
case Decl::OMPCapturedExpr:
|
||||
case Decl::Label: // FIXME: Is this right??
|
||||
case Decl::ClassScopeFunctionSpecialization:
|
||||
case Decl::CXXDeductionGuide:
|
||||
case Decl::Import:
|
||||
case Decl::OMPThreadPrivate:
|
||||
|
Loading…
Reference in New Issue
Block a user