summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2013-11-20 06:45:19 +0000
committerBill Wendling <isanbard@gmail.com>2013-11-20 06:45:19 +0000
commit579d45ff5f92c4f5e31213e31490acdc5bcc5567 (patch)
treee77a9ee3ab14b3221f4030d41b1a7a743f94a2ec
parent287d8b32ee7ee0e65674c433c9fe3bbcf1aa834c (diff)
downloadclang-579d45ff5f92c4f5e31213e31490acdc5bcc5567.tar.gz
clang-579d45ff5f92c4f5e31213e31490acdc5bcc5567.tar.bz2
clang-579d45ff5f92c4f5e31213e31490acdc5bcc5567.tar.xz
Merging r195154:
------------------------------------------------------------------------ r195154 | rafael | 2013-11-19 13:07:04 -0800 (Tue, 19 Nov 2013) | 15 lines Further fixes when thiscall is the default for methods. The previous patches tried to deduce the correct function type. I now realize this is not possible in general. Consider class foo { template <typename T> static void bar(T v); }; extern template void foo::bar(const void *); We will only know that bar is static after a lookup, so we have to handle this in the template instantiation code. This patch reverts my previous two changes (but not the tests) and instead handles the issue in DeduceTemplateArguments. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_34@195226 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp19
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp17
-rw-r--r--lib/Sema/SemaType.cpp279
-rw-r--r--test/SemaCXX/decl-microsoft-call-conv.cpp7
4 files changed, 160 insertions, 162 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 6d40e00b21..e9977d42aa 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -6501,11 +6501,11 @@ bool Sema::CheckFunctionTemplateSpecialization(
// it will be a static member function until we know which template it
// specializes), so adjust it now assuming it specializes this template.
QualType FT = FD->getType();
- const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
- FunctionDecl *TmplFD = FunTmpl->getTemplatedDecl();
if (FD->isConstexpr()) {
- CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(TmplFD);
+ CXXMethodDecl *OldMD =
+ dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
if (OldMD && OldMD->isConst()) {
+ const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals |= Qualifiers::Const;
FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
@@ -6513,19 +6513,6 @@ bool Sema::CheckFunctionTemplateSpecialization(
}
}
- // Ignore differences in calling convention and noreturn until decl
- // merging.
- const FunctionProtoType *TmplFT =
- TmplFD->getType()->castAs<FunctionProtoType>();
- if (FPT->getCallConv() != TmplFT->getCallConv() ||
- FPT->getNoReturnAttr() != TmplFT->getNoReturnAttr()) {
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.ExtInfo = EPI.ExtInfo.withCallingConv(TmplFT->getCallConv());
- EPI.ExtInfo = EPI.ExtInfo.withNoReturn(TmplFT->getNoReturnAttr());
- FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
- EPI);
- }
-
// C++ [temp.expl.spec]p11:
// A trailing template-argument can be left unspecified in the
// template-id naming an explicit function template specialization
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index b401db21a8..56df8bab9b 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3538,6 +3538,23 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
+ if (!InOverloadResolution && !ArgFunctionType.isNull()) {
+ const FunctionProtoType *FunctionTypeP =
+ FunctionType->castAs<FunctionProtoType>();
+ CallingConv CC = FunctionTypeP->getCallConv();
+ bool NoReturn = FunctionTypeP->getNoReturnAttr();
+ const FunctionProtoType *ArgFunctionTypeP =
+ ArgFunctionType->getAs<FunctionProtoType>();
+ if (ArgFunctionTypeP->getCallConv() != CC ||
+ ArgFunctionTypeP->getNoReturnAttr() != NoReturn) {
+ FunctionType::ExtInfo EI =
+ ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
+ EI = EI.withNoReturn(NoReturn);
+ ArgFunctionTypeP = cast<FunctionProtoType>(
+ Context.adjustFunctionType(ArgFunctionTypeP, EI));
+ ArgFunctionType = QualType(ArgFunctionTypeP, 0);
+ }
+ }
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index e5e68063a4..aa7459de27 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2506,136 +2506,6 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
IsCXXInstanceMethod);
}
-namespace {
- /// A helper class to unwrap a type down to a function for the
- /// purposes of applying attributes there.
- ///
- /// Use:
- /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
- /// if (unwrapped.isFunctionType()) {
- /// const FunctionType *fn = unwrapped.get();
- /// // change fn somehow
- /// T = unwrapped.wrap(fn);
- /// }
- struct FunctionTypeUnwrapper {
- enum WrapKind {
- Desugar,
- Parens,
- Pointer,
- BlockPointer,
- Reference,
- MemberPointer
- };
-
- QualType Original;
- const FunctionType *Fn;
- SmallVector<unsigned char /*WrapKind*/, 8> Stack;
-
- FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
- while (true) {
- const Type *Ty = T.getTypePtr();
- if (isa<FunctionType>(Ty)) {
- Fn = cast<FunctionType>(Ty);
- return;
- } else if (isa<ParenType>(Ty)) {
- T = cast<ParenType>(Ty)->getInnerType();
- Stack.push_back(Parens);
- } else if (isa<PointerType>(Ty)) {
- T = cast<PointerType>(Ty)->getPointeeType();
- Stack.push_back(Pointer);
- } else if (isa<BlockPointerType>(Ty)) {
- T = cast<BlockPointerType>(Ty)->getPointeeType();
- Stack.push_back(BlockPointer);
- } else if (isa<MemberPointerType>(Ty)) {
- T = cast<MemberPointerType>(Ty)->getPointeeType();
- Stack.push_back(MemberPointer);
- } else if (isa<ReferenceType>(Ty)) {
- T = cast<ReferenceType>(Ty)->getPointeeType();
- Stack.push_back(Reference);
- } else {
- const Type *DTy = Ty->getUnqualifiedDesugaredType();
- if (Ty == DTy) {
- Fn = 0;
- return;
- }
-
- T = QualType(DTy, 0);
- Stack.push_back(Desugar);
- }
- }
- }
-
- bool isFunctionType() const { return (Fn != 0); }
- const FunctionType *get() const { return Fn; }
-
- QualType wrap(Sema &S, const FunctionType *New) {
- // If T wasn't modified from the unwrapped type, do nothing.
- if (New == get()) return Original;
-
- Fn = New;
- return wrap(S.Context, Original, 0);
- }
-
- private:
- QualType wrap(ASTContext &C, QualType Old, unsigned I) {
- if (I == Stack.size())
- return C.getQualifiedType(Fn, Old.getQualifiers());
-
- // Build up the inner type, applying the qualifiers from the old
- // type to the new type.
- SplitQualType SplitOld = Old.split();
-
- // As a special case, tail-recurse if there are no qualifiers.
- if (SplitOld.Quals.empty())
- return wrap(C, SplitOld.Ty, I);
- return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
- }
-
- QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
- if (I == Stack.size()) return QualType(Fn, 0);
-
- switch (static_cast<WrapKind>(Stack[I++])) {
- case Desugar:
- // This is the point at which we potentially lose source
- // information.
- return wrap(C, Old->getUnqualifiedDesugaredType(), I);
-
- case Parens: {
- QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
- return C.getParenType(New);
- }
-
- case Pointer: {
- QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
- return C.getPointerType(New);
- }
-
- case BlockPointer: {
- QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
- return C.getBlockPointerType(New);
- }
-
- case MemberPointer: {
- const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
- QualType New = wrap(C, OldMPT->getPointeeType(), I);
- return C.getMemberPointerType(New, OldMPT->getClass());
- }
-
- case Reference: {
- const ReferenceType *OldRef = cast<ReferenceType>(Old);
- QualType New = wrap(C, OldRef->getPointeeType(), I);
- if (isa<LValueReferenceType>(OldRef))
- return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
- else
- return C.getRValueReferenceType(New);
- }
- }
-
- llvm_unreachable("unknown wrapping kind");
- }
- };
-}
-
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
@@ -3239,27 +3109,14 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// top-level template type arguments.
bool FreeFunction;
if (!D.getCXXScopeSpec().isSet()) {
- const DeclSpec &Spec = D.getDeclSpec();
- FreeFunction = (D.getContext() != Declarator::MemberContext &&
- D.getContext() != Declarator::LambdaExprContext) ||
- Spec.isFriendSpecified() ||
- Spec.getStorageClassSpec() == DeclSpec::SCS_typedef;
+ FreeFunction = ((D.getContext() != Declarator::MemberContext &&
+ D.getContext() != Declarator::LambdaExprContext) ||
+ D.getDeclSpec().isFriendSpecified());
} else {
DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
FreeFunction = (DC && !DC->isRecord());
}
- if (!S.getCallingConvAttributedType(T)) {
- CallingConv CC =
- Context.getDefaultCallingConvention(FnTy->isVariadic(), !FreeFunction);
- if (CC != FnTy->getCallConv()) {
- FunctionType::ExtInfo EI = FnTy->getExtInfo().withCallingConv(CC);
- FnTy = cast<FunctionProtoType>(S.Context.adjustFunctionType(FnTy, EI));
- FunctionTypeUnwrapper Unwrapped(S, T);
- T = Unwrapped.wrap(S, FnTy);
- }
- }
-
// C++11 [dcl.fct]p6 (w/DR1417):
// An attempt to specify a function type with a cv-qualifier-seq or a
// ref-qualifier (including by typedef-name) is ill-formed unless it is:
@@ -4360,6 +4217,136 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state,
return true;
}
+namespace {
+ /// A helper class to unwrap a type down to a function for the
+ /// purposes of applying attributes there.
+ ///
+ /// Use:
+ /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
+ /// if (unwrapped.isFunctionType()) {
+ /// const FunctionType *fn = unwrapped.get();
+ /// // change fn somehow
+ /// T = unwrapped.wrap(fn);
+ /// }
+ struct FunctionTypeUnwrapper {
+ enum WrapKind {
+ Desugar,
+ Parens,
+ Pointer,
+ BlockPointer,
+ Reference,
+ MemberPointer
+ };
+
+ QualType Original;
+ const FunctionType *Fn;
+ SmallVector<unsigned char /*WrapKind*/, 8> Stack;
+
+ FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
+ while (true) {
+ const Type *Ty = T.getTypePtr();
+ if (isa<FunctionType>(Ty)) {
+ Fn = cast<FunctionType>(Ty);
+ return;
+ } else if (isa<ParenType>(Ty)) {
+ T = cast<ParenType>(Ty)->getInnerType();
+ Stack.push_back(Parens);
+ } else if (isa<PointerType>(Ty)) {
+ T = cast<PointerType>(Ty)->getPointeeType();
+ Stack.push_back(Pointer);
+ } else if (isa<BlockPointerType>(Ty)) {
+ T = cast<BlockPointerType>(Ty)->getPointeeType();
+ Stack.push_back(BlockPointer);
+ } else if (isa<MemberPointerType>(Ty)) {
+ T = cast<MemberPointerType>(Ty)->getPointeeType();
+ Stack.push_back(MemberPointer);
+ } else if (isa<ReferenceType>(Ty)) {
+ T = cast<ReferenceType>(Ty)->getPointeeType();
+ Stack.push_back(Reference);
+ } else {
+ const Type *DTy = Ty->getUnqualifiedDesugaredType();
+ if (Ty == DTy) {
+ Fn = 0;
+ return;
+ }
+
+ T = QualType(DTy, 0);
+ Stack.push_back(Desugar);
+ }
+ }
+ }
+
+ bool isFunctionType() const { return (Fn != 0); }
+ const FunctionType *get() const { return Fn; }
+
+ QualType wrap(Sema &S, const FunctionType *New) {
+ // If T wasn't modified from the unwrapped type, do nothing.
+ if (New == get()) return Original;
+
+ Fn = New;
+ return wrap(S.Context, Original, 0);
+ }
+
+ private:
+ QualType wrap(ASTContext &C, QualType Old, unsigned I) {
+ if (I == Stack.size())
+ return C.getQualifiedType(Fn, Old.getQualifiers());
+
+ // Build up the inner type, applying the qualifiers from the old
+ // type to the new type.
+ SplitQualType SplitOld = Old.split();
+
+ // As a special case, tail-recurse if there are no qualifiers.
+ if (SplitOld.Quals.empty())
+ return wrap(C, SplitOld.Ty, I);
+ return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
+ }
+
+ QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
+ if (I == Stack.size()) return QualType(Fn, 0);
+
+ switch (static_cast<WrapKind>(Stack[I++])) {
+ case Desugar:
+ // This is the point at which we potentially lose source
+ // information.
+ return wrap(C, Old->getUnqualifiedDesugaredType(), I);
+
+ case Parens: {
+ QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
+ return C.getParenType(New);
+ }
+
+ case Pointer: {
+ QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
+ return C.getPointerType(New);
+ }
+
+ case BlockPointer: {
+ QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
+ return C.getBlockPointerType(New);
+ }
+
+ case MemberPointer: {
+ const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
+ QualType New = wrap(C, OldMPT->getPointeeType(), I);
+ return C.getMemberPointerType(New, OldMPT->getClass());
+ }
+
+ case Reference: {
+ const ReferenceType *OldRef = cast<ReferenceType>(Old);
+ QualType New = wrap(C, OldRef->getPointeeType(), I);
+ if (isa<LValueReferenceType>(OldRef))
+ return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
+ else
+ return C.getRValueReferenceType(New);
+ }
+ }
+
+ llvm_unreachable("unknown wrapping kind");
+ }
+ };
+}
+
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
AttributeList &Attr,
QualType &Type) {
diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp
index e47a5c2a5c..a1a6d0b289 100644
--- a/test/SemaCXX/decl-microsoft-call-conv.cpp
+++ b/test/SemaCXX/decl-microsoft-call-conv.cpp
@@ -176,3 +176,10 @@ namespace test3 {
void bah() {}
void baz() { zed(bah); }
}
+
+namespace test4 {
+ class foo {
+ template <typename T> static void bar(T v);
+ };
+ extern template void foo::bar(const void *);
+}