summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-07-19 19:51:03 +0000
committerReid Kleckner <reid@kleckner.net>2013-07-19 19:51:03 +0000
commit569b8f83a4188048c910cf50050ea8c6ea31293f (patch)
tree946bfa25a5053ba62f31e7b31740d46602d6eaec /clang/lib
parent8917ad5d1f1f336dcbb42bd395b02ee0a8618688 (diff)
downloadbcm5719-llvm-569b8f83a4188048c910cf50050ea8c6ea31293f.tar.gz
bcm5719-llvm-569b8f83a4188048c910cf50050ea8c6ea31293f.zip
Create calling convention AttributedType sugar nodes
Canonical types are unchanged. The type printer had to be changed to avoid printing any non-default implicit calling convention as well as the calling convention attribute. Reviewers: rjmccall Differential Revision: http://llvm-reviews.chandlerc.com/D1132 llvm-svn: 186714
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Type.cpp41
-rw-r--r--clang/lib/AST/TypePrinter.cpp73
-rw-r--r--clang/lib/Sema/SemaType.cpp45
3 files changed, 121 insertions, 38 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 4068b2b8988..44da348b0b7 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1842,6 +1842,47 @@ bool TagType::isBeingDefined() const {
return getDecl()->isBeingDefined();
}
+bool AttributedType::isMSTypeSpec() const {
+ switch (getAttrKind()) {
+ default: return false;
+ case attr_ptr32:
+ case attr_ptr64:
+ case attr_sptr:
+ case attr_uptr:
+ return true;
+ }
+ llvm_unreachable("invalid attr kind");
+}
+
+bool AttributedType::isCallingConv() const {
+ switch (getAttrKind()) {
+ case attr_ptr32:
+ case attr_ptr64:
+ case attr_sptr:
+ case attr_uptr:
+ case attr_address_space:
+ case attr_regparm:
+ case attr_vector_size:
+ case attr_neon_vector_type:
+ case attr_neon_polyvector_type:
+ case attr_objc_gc:
+ case attr_objc_ownership:
+ case attr_noreturn:
+ return false;
+ case attr_pcs:
+ case attr_pcs_vfp:
+ case attr_cdecl:
+ case attr_fastcall:
+ case attr_stdcall:
+ case attr_thiscall:
+ case attr_pascal:
+ case attr_pnaclcall:
+ case attr_inteloclbicc:
+ return true;
+ }
+ llvm_unreachable("invalid attr kind");
+}
+
CXXRecordDecl *InjectedClassNameType::getDecl() const {
return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index d19c6a94508..3b917aa33fb 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -81,10 +81,11 @@ namespace {
class TypePrinter {
PrintingPolicy Policy;
bool HasEmptyPlaceHolder;
+ bool InsideCCAttribute;
public:
explicit TypePrinter(const PrintingPolicy &Policy)
- : Policy(Policy), HasEmptyPlaceHolder(false) { }
+ : Policy(Policy), HasEmptyPlaceHolder(false), InsideCCAttribute(false) { }
void print(const Type *ty, Qualifiers qs, raw_ostream &OS,
StringRef PlaceHolder);
@@ -630,36 +631,40 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
OS << ')';
FunctionType::ExtInfo Info = T->getExtInfo();
- switch(Info.getCC()) {
- case CC_Default: break;
- case CC_C:
- OS << " __attribute__((cdecl))";
- break;
- case CC_X86StdCall:
- OS << " __attribute__((stdcall))";
- break;
- case CC_X86FastCall:
- OS << " __attribute__((fastcall))";
- break;
- case CC_X86ThisCall:
- OS << " __attribute__((thiscall))";
- break;
- case CC_X86Pascal:
- OS << " __attribute__((pascal))";
- break;
- case CC_AAPCS:
- OS << " __attribute__((pcs(\"aapcs\")))";
- break;
- case CC_AAPCS_VFP:
- OS << " __attribute__((pcs(\"aapcs-vfp\")))";
- break;
- case CC_PnaclCall:
- OS << " __attribute__((pnaclcall))";
- break;
- case CC_IntelOclBicc:
- OS << " __attribute__((intel_ocl_bicc))";
- break;
+
+ if (!InsideCCAttribute) {
+ switch (Info.getCC()) {
+ case CC_Default: break;
+ case CC_C:
+ OS << " __attribute__((cdecl))";
+ break;
+ case CC_X86StdCall:
+ OS << " __attribute__((stdcall))";
+ break;
+ case CC_X86FastCall:
+ OS << " __attribute__((fastcall))";
+ break;
+ case CC_X86ThisCall:
+ OS << " __attribute__((thiscall))";
+ break;
+ case CC_X86Pascal:
+ OS << " __attribute__((pascal))";
+ break;
+ case CC_AAPCS:
+ OS << " __attribute__((pcs(\"aapcs\")))";
+ break;
+ case CC_AAPCS_VFP:
+ OS << " __attribute__((pcs(\"aapcs-vfp\")))";
+ break;
+ case CC_PnaclCall:
+ OS << " __attribute__((pnaclcall))";
+ break;
+ case CC_IntelOclBicc:
+ OS << " __attribute__((intel_ocl_bicc))";
+ break;
+ }
}
+
if (Info.getNoReturn())
OS << " __attribute__((noreturn))";
if (Info.getRegParm())
@@ -1089,7 +1094,7 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
case AttributedType::attr_ptr64: OS << " __ptr64"; break;
case AttributedType::attr_sptr: OS << " __sptr"; break;
case AttributedType::attr_uptr: OS << " __uptr"; break;
-}
+ }
spaceBeforePlaceHolder(OS);
}
}
@@ -1105,6 +1110,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
if (T->isMSTypeSpec())
return;
+ // If this is a calling convention attribute, don't print the implicit CC from
+ // the modified type.
+ SaveAndRestore<bool> MaybeSuppressCC(InsideCCAttribute, T->isCallingConv());
+
+ printAfter(T->getModifiedType(), OS);
+
OS << " __attribute__((";
switch (T->getAttrKind()) {
default: llvm_unreachable("This attribute should have been handled already");
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 42e33faca38..2e0a06b5c79 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -546,12 +546,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
return true;
}
- if (handleFunctionTypeAttr(state, attr, declSpecType)) {
- spliceAttrOutOfList(attr, attrList);
- return true;
- }
-
- return false;
+ return handleFunctionTypeAttr(state, attr, declSpecType);
}
/// A function type attribute was written in the decl spec. Try to
@@ -3345,6 +3340,7 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
case AttributedType::attr_pcs:
+ case AttributedType::attr_pcs_vfp:
return AttributeList::AT_Pcs;
case AttributedType::attr_pnaclcall:
return AttributeList::AT_PnaclCall;
@@ -4302,6 +4298,36 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
return false;
}
+static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
+ assert(!Attr.isInvalid());
+ switch (Attr.getKind()) {
+ default:
+ llvm_unreachable("not a calling convention attribute");
+ case AttributeList::AT_CDecl:
+ return AttributedType::attr_cdecl;
+ case AttributeList::AT_FastCall:
+ return AttributedType::attr_fastcall;
+ case AttributeList::AT_StdCall:
+ return AttributedType::attr_stdcall;
+ case AttributeList::AT_ThisCall:
+ return AttributedType::attr_thiscall;
+ case AttributeList::AT_Pascal:
+ return AttributedType::attr_pascal;
+ case AttributeList::AT_Pcs: {
+ // We know attr is valid so it can only have one of two strings args.
+ StringLiteral *Str = cast<StringLiteral>(Attr.getArg(0));
+ return llvm::StringSwitch<AttributedType::Kind>(Str->getString())
+ .Case("aapcs", AttributedType::attr_pcs)
+ .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
+ }
+ case AttributeList::AT_PnaclCall:
+ return AttributedType::attr_pnaclcall;
+ case AttributeList::AT_IntelOclBicc:
+ return AttributedType::attr_inteloclbicc;
+ }
+ llvm_unreachable("unexpected attribute kind!");
+}
+
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
static bool handleFunctionTypeAttr(TypeProcessingState &state,
@@ -4421,8 +4447,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
}
}
+ // Modify the CC from the wrapped function type, wrap it all back, and then
+ // wrap the whole thing in an AttributedType as written. The modified type
+ // might have a different CC if we ignored the attribute.
FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
- type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ QualType Equivalent =
+ unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
+ type = S.Context.getAttributedType(getCCTypeAttrKind(attr), type, Equivalent);
return true;
}
OpenPOWER on IntegriCloud