[cfe-commits] r40951 - in /cfe/trunk: AST/Expr.cpp AST/Type.cpp include/clang/AST/Expr.h include/clang/AST/Type.h test/Parser/builtin_classify_type.c
Steve Naroff
snaroff at apple.com
Wed Aug 8 15:15:55 PDT 2007
Author: snaroff
Date: Wed Aug 8 17:15:55 2007
New Revision: 40951
URL: http://llvm.org/viewvc/llvm-project?rev=40951&view=rev
Log:
Finish implementing __builtin_classify_type()...
Added:
cfe/trunk/test/Parser/builtin_classify_type.c
Modified:
cfe/trunk/AST/Expr.cpp
cfe/trunk/AST/Type.cpp
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/Type.h
Modified: cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Expr.cpp?rev=40951&r1=40950&r2=40951&view=diff
==============================================================================
--- cfe/trunk/AST/Expr.cpp (original)
+++ cfe/trunk/AST/Expr.cpp Wed Aug 8 17:15:55 2007
@@ -85,6 +85,75 @@
RParenLoc = rparenloc;
}
+bool CallExpr::isBuiltinClassifyType(llvm::APSInt &Result) const {
+ // The following enum mimics gcc's internal "typeclass.h" file.
+ enum gcc_type_class {
+ no_type_class = -1,
+ void_type_class, integer_type_class, char_type_class,
+ enumeral_type_class, boolean_type_class,
+ pointer_type_class, reference_type_class, offset_type_class,
+ real_type_class, complex_type_class,
+ function_type_class, method_type_class,
+ record_type_class, union_type_class,
+ array_type_class, string_type_class,
+ lang_type_class
+ };
+ Result.setIsSigned(true);
+
+ // All simple function calls (e.g. func()) are implicitly cast to pointer to
+ // function. As a result, we try and obtain the DeclRefExpr from the
+ // ImplicitCastExpr.
+ const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
+ if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
+ return false;
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
+ if (!DRE)
+ return false;
+
+ // We have a DeclRefExpr.
+ if (strcmp(DRE->getDecl()->getName(), "__builtin_classify_type") == 0) {
+ // If no argument was supplied, default to "no_type_class". This isn't
+ // ideal, however it's what gcc does.
+ Result = static_cast<uint64_t>(no_type_class);
+ if (NumArgs >= 1) {
+ QualType argType = getArg(0)->getType();
+
+ if (argType->isVoidType())
+ Result = void_type_class;
+ else if (argType->isEnumeralType())
+ Result = enumeral_type_class;
+ else if (argType->isBooleanType())
+ Result = boolean_type_class;
+ else if (argType->isCharType())
+ Result = string_type_class; // gcc doesn't appear to use char_type_class
+ else if (argType->isIntegerType())
+ Result = integer_type_class;
+ else if (argType->isPointerType())
+ Result = pointer_type_class;
+ else if (argType->isReferenceType())
+ Result = reference_type_class;
+ else if (argType->isRealType())
+ Result = real_type_class;
+ else if (argType->isComplexType())
+ Result = complex_type_class;
+ else if (argType->isFunctionType())
+ Result = function_type_class;
+ else if (argType->isStructureType())
+ Result = record_type_class;
+ else if (argType->isUnionType())
+ Result = union_type_class;
+ else if (argType->isArrayType())
+ Result = array_type_class;
+ else if (argType->isUnionType())
+ Result = union_type_class;
+ else // FIXME: offset_type_class, method_type_class, & lang_type_class?
+ assert(1 && "CallExpr::isBuiltinClassifyType(): unimplemented type");
+ }
+ return true;
+ }
+ return false;
+}
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
@@ -311,6 +380,14 @@
Result = TCE->typesAreCompatible();
break;
}
+ case CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(this);
+ Result.zextOrTrunc(Ctx.getTypeSize(getType(), CE->getLocStart()));
+ if (CE->isBuiltinClassifyType(Result))
+ break;
+ if (Loc) *Loc = getLocStart();
+ return false;
+ }
case DeclRefExprClass:
if (const EnumConstantDecl *D =
dyn_cast<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl())) {
Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=40951&r1=40950&r2=40951&view=diff
==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Wed Aug 8 17:15:55 2007
@@ -340,6 +340,26 @@
return false;
}
+bool Type::isEnumeralType() const {
+ if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
+ return TT->getDecl()->getKind() == Decl::Enum;
+ return false;
+}
+
+bool Type::isBooleanType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Bool;
+ return false;
+}
+
+bool Type::isCharType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Char_U ||
+ BT->getKind() == BuiltinType::UChar ||
+ BT->getKind() == BuiltinType::Char_S;
+ return false;
+}
+
bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=40951&r1=40950&r2=40951&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Aug 8 17:15:55 2007
@@ -424,6 +424,8 @@
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
+ bool isBuiltinClassifyType(llvm::APSInt &Result) const;
+
SourceRange getSourceRange() const {
return SourceRange(Fn->getLocStart(), RParenLoc);
}
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=40951&r1=40950&r2=40951&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Aug 8 17:15:55 2007
@@ -231,6 +231,9 @@
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs.
bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
+ bool isEnumeralType() const;
+ bool isBooleanType() const;
+ bool isCharType() const;
/// Floating point categories.
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
Added: cfe/trunk/test/Parser/builtin_classify_type.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/builtin_classify_type.c?rev=40951&view=auto
==============================================================================
--- cfe/trunk/test/Parser/builtin_classify_type.c (added)
+++ cfe/trunk/test/Parser/builtin_classify_type.c Wed Aug 8 17:15:55 2007
@@ -0,0 +1,21 @@
+// RUN: clang -parse-ast-check %s
+
+struct foo { int a; };
+
+int main() {
+ int a;
+ float b;
+ double d;
+ struct foo s;
+
+ static int ary[__builtin_classify_type(a)];
+ static int ary2[(__builtin_classify_type)(a)]; // expected-error{{variable length array declared outside of any function}}
+ static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{variable length array declared outside of any function}}
+
+ int result;
+
+ result = __builtin_classify_type(a);
+ result = __builtin_classify_type(b);
+ result = __builtin_classify_type(d);
+ result = __builtin_classify_type(s);
+}
More information about the cfe-commits
mailing list