[cfe-commits] r95291 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/AST/TypePrinter.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaType.cpp test/Sema/callingconv.c
John McCall
rjmccall at apple.com
Wed Feb 3 21:44:45 PST 2010
Author: rjmccall
Date: Wed Feb 3 23:44:44 2010
New Revision: 95291
URL: http://llvm.org/viewvc/llvm-project?rev=95291&view=rev
Log:
Allow calling convention attributes to apply to types. Patch by Chip Davis!
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/AST/TypePrinter.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/Sema/callingconv.c
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Feb 3 23:44:44 2010
@@ -1766,10 +1766,11 @@
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getResultType(), getNoReturnAttr());
+ Profile(ID, getResultType(), getNoReturnAttr(), getCallConv());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
- bool NoReturn) {
+ bool NoReturn, CallingConv CallConv) {
+ ID.AddInteger(CallConv);
ID.AddInteger(NoReturn);
ID.AddPointer(ResultType.getAsOpaquePtr());
}
@@ -1892,7 +1893,7 @@
bool isVariadic, unsigned TypeQuals,
bool hasExceptionSpec, bool anyExceptionSpec,
unsigned NumExceptions, exception_iterator Exs,
- bool NoReturn);
+ bool NoReturn, CallingConv CallConv);
};
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Feb 3 23:44:44 2010
@@ -1716,7 +1716,7 @@
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
- FunctionNoProtoType::Profile(ID, ResultTy, NoReturn);
+ FunctionNoProtoType::Profile(ID, ResultTy, NoReturn, CallConv);
void *InsertPos = 0;
if (FunctionNoProtoType *FT =
@@ -1736,7 +1736,7 @@
}
FunctionNoProtoType *New = new (*this, TypeAlignment)
- FunctionNoProtoType(ResultTy, Canonical, NoReturn);
+ FunctionNoProtoType(ResultTy, Canonical, NoReturn, CallConv);
Types.push_back(New);
FunctionNoProtoTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -1755,7 +1755,7 @@
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
- NumExs, ExArray, NoReturn);
+ NumExs, ExArray, NoReturn, CallConv);
void *InsertPos = 0;
if (FunctionProtoType *FTP =
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Feb 3 23:44:44 2010
@@ -815,7 +815,8 @@
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool anyExceptionSpec, unsigned NumExceptions,
- exception_iterator Exs, bool NoReturn) {
+ exception_iterator Exs, bool NoReturn,
+ CallingConv CallConv) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@@ -828,12 +829,14 @@
ID.AddPointer(Exs[i].getAsOpaquePtr());
}
ID.AddInteger(NoReturn);
+ ID.AddInteger(CallConv);
}
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
- getNumExceptions(), exception_begin(), getNoReturnAttr());
+ getNumExceptions(), exception_begin(), getNoReturnAttr(),
+ getCallConv());
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Wed Feb 3 23:44:44 2010
@@ -271,6 +271,19 @@
S += ")";
+ switch(T->getCallConv()) {
+ case CC_Default:
+ default: break;
+ case CC_C:
+ S += " __attribute__((cdecl))";
+ break;
+ case CC_X86StdCall:
+ S += " __attribute__((stdcall))";
+ break;
+ case CC_X86FastCall:
+ S += " __attribute__((fastcall))";
+ break;
+ }
if (T->getNoReturnAttr())
S += " __attribute__((noreturn))";
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 3 23:44:44 2010
@@ -560,7 +560,9 @@
// Type Analysis / Processing: SemaType.cpp.
//
QualType adjustParameterType(QualType T);
- void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
+ void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL,
+ bool HandleCallConvAttributes = false,
+ bool HandleOnlyCallConv = false);
QualType BuildPointerType(QualType T, unsigned Quals,
SourceLocation Loc, DeclarationName Entity);
QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 3 23:44:44 2010
@@ -901,6 +901,14 @@
return Sema::CXXCopyAssignment;
}
+static const char* getCallConvName(CallingConv CC) {
+ switch (CC) {
+ default: return "cdecl";
+ case CC_X86StdCall: return "stdcall";
+ case CC_X86FastCall: return "fastcall";
+ }
+}
+
/// MergeFunctionDecl - We just parsed a function 'New' from
/// declarator D which has the same name and scope as a previous
/// declaration 'Old'. Figure out how to resolve this situation,
@@ -958,6 +966,33 @@
return true;
}
+ // If a function is first declared with a calling convention, but is
+ // later declared or defined without one, the second decl assumes the
+ // calling convention of the first.
+ //
+ // For the new decl, we have to look at the NON-canonical type to tell the
+ // difference between a function that really doesn't have a calling
+ // convention and one that is declared cdecl. That's because in
+ // canonicalization (see ASTContext.cpp), cdecl is canonicalized away
+ // because it is the default calling convention.
+ //
+ // Note also that we DO NOT return at this point, because we still have
+ // other tests to run.
+ const FunctionType *OldType = OldQType->getAs<FunctionType>();
+ const FunctionType *NewType = New->getType()->getAs<FunctionType>();
+ if (OldType->getCallConv() != CC_Default &&
+ NewType->getCallConv() == CC_Default) {
+ NewQType = Context.getCallConvType(NewQType, OldType->getCallConv());
+ New->setType(NewQType);
+ NewQType = Context.getCanonicalType(NewQType);
+ } else if (OldType->getCallConv() != NewType->getCallConv()) {
+ // Calling conventions really aren't compatible, so complain.
+ Diag(New->getLocation(), diag::err_attributes_are_not_compatible)
+ << getCallConvName(NewType->getCallConv())
+ << getCallConvName(OldType->getCallConv());
+ return true;
+ }
+
if (getLangOptions().CPlusPlus) {
// (C++98 13.1p2):
// Certain function declarations cannot be overloaded:
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Feb 3 23:44:44 2010
@@ -948,6 +948,12 @@
}
// Attribute can be applied only to functions.
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either. All the function-pointer stuff is handled in
+ // SemaType.cpp.
+ ValueDecl *VD = dyn_cast<ValueDecl>(d);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 0 /*function*/;
@@ -980,6 +986,11 @@
}
// Attribute can be applied only to functions.
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either.
+ ValueDecl *VD = dyn_cast<ValueDecl>(d);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 0 /*function*/;
@@ -1019,6 +1030,11 @@
return;
}
+ // If we try to apply it to a function pointer, don't warn, but don't
+ // do anything, either.
+ ValueDecl *VD = dyn_cast<ValueDecl>(d);
+ if (VD && VD->getType()->isFunctionPointerType())
+ return;
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << 0 /*function*/;
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 3 23:44:44 2010
@@ -1241,7 +1241,7 @@
// See if there are any attributes on this declarator chunk.
if (const AttributeList *AL = DeclType.getAttrs())
- ProcessTypeAttributeList(T, AL);
+ ProcessTypeAttributeList(T, AL, true);
}
if (getLangOptions().CPlusPlus && T->isFunctionType()) {
@@ -1274,7 +1274,10 @@
// If there were any type attributes applied to the decl itself (not the
// type, apply the type attribute to the type!)
if (const AttributeList *Attrs = D.getAttributes())
- ProcessTypeAttributeList(T, Attrs);
+ ProcessTypeAttributeList(T, Attrs, true);
+ // Also look in the decl spec.
+ if (const AttributeList *Attrs = D.getDeclSpec().getAttributes())
+ ProcessTypeAttributeList(T, Attrs, true, true);
if (TInfo) {
if (D.isInvalidType())
@@ -1612,6 +1615,36 @@
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
+/// HandleCDeclTypeAttribute - Process the cdecl attribute on the
+/// specified type. The attribute contains 0 arguments.
+static void HandleCDeclTypeAttribute(QualType &Type,
+ const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0)
+ return;
+
+ // We only apply this to a pointer to function.
+ if (!Type->isFunctionPointerType()
+ && !Type->isFunctionType())
+ return;
+
+ Type = S.Context.getCallConvType(Type, CC_C);
+}
+
+/// HandleFastCallTypeAttribute - Process the fastcall attribute on the
+/// specified type. The attribute contains 0 arguments.
+static void HandleFastCallTypeAttribute(QualType &Type,
+ const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0)
+ return;
+
+ // We only apply this to a pointer to function.
+ if (!Type->isFunctionPointerType()
+ && !Type->isFunctionType())
+ return;
+
+ Type = S.Context.getCallConvType(Type, CC_X86FastCall);
+}
+
/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the
/// specified type. The attribute contains 1 argument, weak or strong.
static void HandleObjCGCTypeAttribute(QualType &Type,
@@ -1661,6 +1694,21 @@
Type = S.Context.getNoReturnType(Type);
}
+/// HandleStdCallTypeAttribute - Process the stdcall attribute on the
+/// specified type. The attribute contains 0 arguments.
+static void HandleStdCallTypeAttribute(QualType &Type,
+ const AttributeList &Attr, Sema &S) {
+ if (Attr.getNumArgs() != 0)
+ return;
+
+ // We only apply this to a pointer to function.
+ if (!Type->isFunctionPointerType()
+ && !Type->isFunctionType())
+ return;
+
+ Type = S.Context.getCallConvType(Type, CC_X86StdCall);
+}
+
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
/// and float scalars, although arrays, pointers, and function return values are
/// allowed in conjunction with this construct. Aggregates with this attribute
@@ -1708,7 +1756,12 @@
CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
}
-void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
+void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL,
+ bool HandleCallConvAttributes,
+ bool HandleOnlyCallConv) {
+ if(HandleOnlyCallConv)
+ assert(HandleCallConvAttributes && "Can't not handle call-conv attributes"
+ " while only handling them!");
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
@@ -1719,16 +1772,32 @@
switch (AL->getKind()) {
default: break;
case AttributeList::AT_address_space:
- HandleAddressSpaceTypeAttribute(Result, *AL, *this);
+ if (!HandleOnlyCallConv)
+ HandleAddressSpaceTypeAttribute(Result, *AL, *this);
+ break;
+ case AttributeList::AT_cdecl:
+ if (HandleCallConvAttributes)
+ HandleCDeclTypeAttribute(Result, *AL, *this);
+ break;
+ case AttributeList::AT_fastcall:
+ if (HandleCallConvAttributes)
+ HandleFastCallTypeAttribute(Result, *AL, *this);
break;
case AttributeList::AT_objc_gc:
- HandleObjCGCTypeAttribute(Result, *AL, *this);
+ if (!HandleOnlyCallConv)
+ HandleObjCGCTypeAttribute(Result, *AL, *this);
break;
case AttributeList::AT_noreturn:
- HandleNoReturnTypeAttribute(Result, *AL, *this);
+ if (!HandleOnlyCallConv)
+ HandleNoReturnTypeAttribute(Result, *AL, *this);
+ break;
+ case AttributeList::AT_stdcall:
+ if (HandleCallConvAttributes)
+ HandleStdCallTypeAttribute(Result, *AL, *this);
break;
case AttributeList::AT_vector_size:
- HandleVectorSizeAttr(Result, *AL, *this);
+ if (!HandleOnlyCallConv)
+ HandleVectorSizeAttr(Result, *AL, *this);
break;
}
}
Modified: cfe/trunk/test/Sema/callingconv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/callingconv.c?rev=95291&r1=95290&r2=95291&view=diff
==============================================================================
--- cfe/trunk/test/Sema/callingconv.c (original)
+++ cfe/trunk/test/Sema/callingconv.c Wed Feb 3 23:44:44 2010
@@ -21,3 +21,15 @@
void __attribute__((cdecl)) ctest0() {}
void __attribute__((cdecl(1))) ctest1(float x) {} // expected-error {{attribute requires 0 argument(s)}}
+
+void (__attribute__((fastcall)) *pfoo)(float*) = foo;
+
+void (__attribute__((stdcall)) *pbar)(float*) = bar;
+
+void (__attribute__((cdecl)) *ptest1)(void) = test1; // expected-warning {{incompatible pointer types}}
+
+void (*pctest0)() = ctest0;
+
+void ctest2() {}
+void (__attribute__((cdecl)) *pctest2)() = ctest2;
+
More information about the cfe-commits
mailing list