================
Comment at: include/clang/AST/ASTContext.h:1754-1758
@@ -1758,7 +1753,7 @@
 
   /// \brief Determines whether two calling conventions name the same
   /// calling convention.
   bool isSameCallConv(CallingConv lcc, CallingConv rcc) {
-    return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc));
+    return lcc == rcc;
   }
 
----------------
Richard Smith wrote:
> Is it worth keeping this around?
No.  My plan was to do a follow up to remove it, but there are only 4 callsites 
left, so I'll nuke it now.

================
Comment at: lib/Sema/SemaDecl.cpp:2376
@@ +2375,3 @@
+  if (FirstTypeInfo.getCC() != NewTypeInfo.getCC()) {
+    bool FirstCCExplicit = getCCTypeAttr(First);
+    bool NewCCExplicit = getCCTypeAttr(New);
----------------
Richard Smith wrote:
> I don't think it should matter whether the first CC was implicit or explicit; 
> the rule seems to be simply that all subsequent decls must match the first 
> decl.
That's basically true, but it's probably an error if clang deduces two 
different implicit CCs for the first decl and a redeclaration, with the 
exception of static method definitions.

I'll add an assert.

================
Comment at: lib/Sema/SemaDecl.cpp:2375-2416
@@ -2368,27 +2374,44 @@
 
-  // Inherit the CC from the previous declaration if it was specified
-  // there but not here.
-  } else if (NewTypeInfo.getCC() == CC_Default) {
-    NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
-    RequiresAdjustment = true;
+  if (FirstTypeInfo.getCC() != NewTypeInfo.getCC()) {
+    bool FirstCCExplicit = getCCTypeAttr(First);
+    bool NewCCExplicit = getCCTypeAttr(New);
+    if (FirstCCExplicit && !NewCCExplicit) {
+      // Inherit the CC from the previous declaration if it was specified
+      // there but not here.
+      NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+      RequiresAdjustment = true;
+
+    } else if (!FirstCCExplicit && !NewCCExplicit) {
+      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(First)) {
+        // We can't tell if an out of line method definition is static until
+        // after we resolve overloads and find its canonical declaration.
+        bool IsVariadic = isa<FunctionProtoType>(FirstType) &&
+                          cast<FunctionProtoType>(FirstType)->isVariadic();
+        CallingConv CCStatic =
+            Context.getDefaultCallingConvention(IsVariadic, false);
+        CallingConv CCInstance =
+            Context.getDefaultCallingConvention(IsVariadic, true);
+        if (MD->isStatic() && FirstTypeInfo.getCC() == CCStatic &&
+            NewTypeInfo.getCC() == CCInstance) {
+          NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+          RequiresAdjustment = true;
+        }
+      }
+    }
 
-  // Don't complain about mismatches when the default CC is
-  // effectively the same as the explict one. Only Old decl contains correct
-  // information about storage class of CXXMethod.
-  } else if (OldTypeInfo.getCC() == CC_Default &&
-             isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) {
-    NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
-    RequiresAdjustment = true;
+    if (FirstTypeInfo.getCC() != NewTypeInfo.getCC()) {
+      // Calling conventions aren't compatible, so complain.
+      assert(!Context.isSameCallConv(OldTypeInfo.getCC(), 
NewTypeInfo.getCC()));
+      Diag(New->getLocation(), diag::err_cconv_change)
+        << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
+        << !FirstCCExplicit
+        << (!FirstCCExplicit ? "" :
+            FunctionType::getNameForCallConv(OldTypeInfo.getCC()));
 
-  } else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
-                                     NewTypeInfo.getCC())) {
-    // Calling conventions really aren't compatible, so complain.
-    Diag(New->getLocation(), diag::err_cconv_change)
-      << FunctionType::getNameForCallConv(NewTypeInfo.getCC())
-      << (OldTypeInfo.getCC() == CC_Default)
-      << (OldTypeInfo.getCC() == CC_Default ? "" :
-          FunctionType::getNameForCallConv(OldTypeInfo.getCC()));
-    Diag(Old->getLocation(), diag::note_previous_declaration);
-    return true;
+      // Put the note on the first decl, since it is the one that matters.
+      Diag(Old->getFirstDeclaration()->getLocation(),
+           diag::note_previous_declaration);
+      return true;
+    }
   }
 
----------------
Richard Smith wrote:
> Can you collapse this into
> 
>     if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) {
>       if (!NewExplicit) {
>         NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
>         RequiresAdjustment = true;
>       } else {
>         issue diagnostic
>       }
>     }
Done, plus the assert.

================
Comment at: lib/AST/ASTContext.cpp:2803
@@ -2808,4 +2802,3 @@
     CanonicalEPI.NumExceptions = 0;
-    CanonicalEPI.ExtInfo
-      = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv));
+    CanonicalEPI.ExtInfo = CanonicalEPI.ExtInfo.withCallingConv(CallConv);
 
----------------
Richard Smith wrote:
> This looks redundant.
Gone.

================
Comment at: lib/AST/ASTContext.cpp:7765-7766
@@ -7771,3 +7764,4 @@
 
   FunctionType::ExtInfo EI;
+  EI = EI.withCallingConv(CC_C);
   if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
----------------
Richard Smith wrote:
> This worries me. We default-construct ExtInfo within ExtProtoInfo instances 
> all over the place. Can we make ExtInfo not be default-constructible?
It could be done, but it would require significantly rewriting every 
construction of ExtProtoInfo as well.  ExtInfo() currently zero initializes, 
which happens to be equivalent to CC_C.  How about I make ExtInfo default 
construct with CC_C?

================
Comment at: lib/AST/ASTContext.cpp:7942
@@ -7946,7 +7941,3 @@
 
-CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const {
-  if (CC == CC_C && !LangOpts.MRTD &&
-      getTargetInfo().getCXXABI().isMemberFunctionCCDefault())
-    return CC_Default;
-  return CC;
+  return (LangOpts.MRTD && !IsVariadic) ? CC_X86StdCall : CC_C;
 }
----------------
Richard Smith wrote:
> The IsVariadic check appears to be new here, but I believe it's correct. Do 
> we have test coverage for this?
It looks like the LLVM x86 backend simply lowers x86_stdcallcc as caller 
cleanup, so I don't think this IsVariadic check is necessary.  I added a 
variadic function to the existing -mrtd test, but should it use x86_stdcallcc 
on variadic functions or not?

================
Comment at: lib/Sema/SemaDecl.cpp:6269-6271
@@ +6268,5 @@
+
+  // Ignore dependent types.
+  const FunctionType *FT = R->getAs<FunctionType>();
+  if (!FT) return R;
+
----------------
Richard Smith wrote:
> Can this really happen?
Seems to work with castAs.

================
Comment at: lib/Sema/SemaDecl.cpp:6276
@@ +6275,3 @@
+  while (AT && !AT->isCallingConv())
+    AT = AT->getEquivalentType()->getAsAttributedType();
+  if (AT) return R;
----------------
Richard Smith wrote:
> As before, this should presumably be getModifiedType. Can this share code 
> with getCCTypeAttr?
Done.

================
Comment at: lib/Sema/SemaDeclCXX.cpp:7922
@@ -7906,5 +7921,3 @@
 
-  // Build an exception specification pointing back at this constructor.
-  FunctionProtoType::ExtProtoInfo EPI;
-  EPI.ExceptionSpecType = EST_Unevaluated;
-  EPI.ExceptionSpecDecl = DefaultCon;
+  // Build an exception specification pointing back at this destructor.
+  FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, 
DefaultCon);
----------------
Richard Smith wrote:
> Copy/pasto?
Woops.

================
Comment at: lib/Sema/SemaLookup.cpp:731
@@ -730,3 +730,3 @@
     FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo();
-    EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default);
+    EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C);
     EPI.ExceptionSpecType = EST_None;
----------------
Richard Smith wrote:
> It would seem more appropriate to use ConvTemplate->getTemplatedDecl()'s 
> calling convention here.
That should already be there from the copy.  John McCall added this CC_Default 
assignment in r121763.  I'm not sure why.

================
Comment at: lib/Sema/SemaType.cpp:2446-2450
@@ +2445,7 @@
+
+    if (FoundNonParen) {
+      // If we're not the declarator, we're a regular function type unless 
we're
+      // in a member pointer.
+      IsCXXInstanceMethod =
+          D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
+    } else {
----------------
Richard Smith wrote:
> What happens if a function type becomes a pointer-to-member-function through 
> a typedef-name? For instance:
> 
>   typedef int fn();
>   typedef fn S::*p;
> 
> Presumably this should give a pointer-to-member-function type with a c++ 
> method cc.
> 
> Hmm, what happens here:
> 
>     struct S;
>     template<typename Fn> struct X {
>       typedef Fn S::*p;
>     };
>     X<void()>::p p1;
>     X<__cdecl void()>::p p2;
>     void (S::*p3)();
>     __cdecl void (S::*p4)();
> 
> Does MSVC believe that p1, p2, p3, and p4 have the same type?
MSVC doesn't model the difference between an implicit and explicit CC.  I 
modified the example, and we get these demangled symbols from cl.exe:

  struct S;
  template<typename Fn> struct X {
    typedef Fn S::*p;
  };
  X<void()>::p p1;
  X<void __cdecl ()>::p p2;
  void (S::*p3)();
  void (__cdecl S::*p4)();

  (void (__thiscall S::* p1)(void))
  (void (__thiscall S::* p2)(void))
  (void (__thiscall S::* p3)(void))
  (void (__cdecl S::* p4)(void))

I added tests for this, but clang currently gets some of these wrong.  As 
discussed, I will have to introduce an implicit AttributedType node so that 
MPT->getPointeeType() returns a function type which is canonically thiscall, 
without erasing the typedef from TSI.  That's for a later patch.

================
Comment at: lib/AST/Type.cpp:519-532
@@ -518,1 +518,16 @@
 
+const AttributedType *Type::getAsAttributedType() const {
+  // AttributedTypes are non-canonical, so we can't use 
getAs<AttributedType>().
+  // Instead we have to unwrap each level of sugar iteratively until we get 
back
+  // the same type or find an AttributedType.
+  QualType Prev;
+  QualType T = QualType(this, 0);
+  while (T != Prev) {
+    if (const AttributedType *AT = dyn_cast<AttributedType>(T))
+      return AT;
+    Prev = T;
+    T = T->getLocallyUnqualifiedSingleStepDesugaredType();
+  }
+  return 0;
+}
+
----------------
Richard Smith wrote:
> Please add an explicit specialization for getAs<> here, as we do for 
> TypedefType and TemplateSpecializationType.
Done.

================
Comment at: lib/Sema/SemaDecl.cpp:2243
@@ +2242,3 @@
+  while (AT && !AT->isCallingConv())
+    AT = AT->getEquivalentType()->getAsAttributedType();
+  if (AT) return AT;
----------------
Richard Smith wrote:
> This should presumably be getModifiedType(), in case the equivalent type has 
> lost some of the sugar. (If you apply an attribute which modifies the 
> function type on top of a function type with a calling convention, you're 
> likely to lose the calling convention sugar from the equivalent type.)
Done.  I can't really test this well because we don't build AttributedTypes for 
things like noreturn yet.


http://llvm-reviews.chandlerc.com/D1231
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to