r195154 - Further fixes when thiscall is the default for methods.

Rafael Espindola rafael.espindola at gmail.com
Tue Nov 19 13:07:04 PST 2013


Author: rafael
Date: Tue Nov 19 15:07:04 2013
New Revision: 195154

URL: http://llvm.org/viewvc/llvm-project?rev=195154&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=195154&r1=195153&r2=195154&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 19 15:07:04 2013
@@ -6501,11 +6501,11 @@ bool Sema::CheckFunctionTemplateSpeciali
       // 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::CheckFunctionTemplateSpeciali
         }
       }
 
-      // 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

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=195154&r1=195153&r2=195154&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Nov 19 15:07:04 2013
@@ -3538,6 +3538,23 @@ Sema::DeduceTemplateArguments(FunctionTe
   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);

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=195154&r1=195153&r2=195154&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Nov 19 15:07:04 2013
@@ -2506,136 +2506,6 @@ getCCForDeclaratorChunk(Sema &S, Declara
                                                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) {
@@ -3240,27 +3110,14 @@ static TypeSourceInfo *GetFullTypeForDec
     // 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:
@@ -4361,6 +4218,136 @@ static bool handleObjCGCTypeAttr(TypePro
   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) {

Modified: cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp?rev=195154&r1=195153&r2=195154&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp Tue Nov 19 15:07:04 2013
@@ -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 *);
+}





More information about the cfe-commits mailing list