зеркало из https://github.com/microsoft/clang-1.git
Finish implementing __builtin_classify_type()...
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40951 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6c216160b6
Коммит
13b7c5ff42
77
AST/Expr.cpp
77
AST/Expr.cpp
|
@ -85,6 +85,75 @@ CallExpr::CallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
|
|||
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 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
|||
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())) {
|
||||
|
|
20
AST/Type.cpp
20
AST/Type.cpp
|
@ -340,6 +340,26 @@ bool Type::isIntegerType() const {
|
|||
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 &&
|
||||
|
|
|
@ -424,6 +424,8 @@ public:
|
|||
/// 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);
|
||||
}
|
||||
|
|
|
@ -231,6 +231,9 @@ public:
|
|||
/// 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)
|
||||
|
|
|
@ -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);
|
||||
}
|
Загрузка…
Ссылка в новой задаче