forked from OSchip/llvm-project
Add parsing and AST support for GNU "typeof".
Many small changes to lot's of files. Still some FIXME's, however the basic support is in place. llvm-svn: 40631
This commit is contained in:
parent
dd34d91e1a
commit
ad373bdcfe
|
@ -584,6 +584,18 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) {
|
|||
return QualType(Decl->TypeForDecl, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getTypeOfType(Expr *tofExpr) {
|
||||
QualType Canonical = tofExpr->getType().getCanonicalType();
|
||||
// Note: TypeOfExpr's aren't uniqued.
|
||||
return QualType(new TypeOfExpr(tofExpr, Canonical), 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getTypeOfType(QualType tofType) {
|
||||
QualType Canonical = tofType.getCanonicalType();
|
||||
// Note: TypeOfType's aren't uniqued.
|
||||
return QualType(new TypeOfType(tofType, Canonical), 0);
|
||||
}
|
||||
|
||||
/// getTagDeclType - Return the unique reference to the type for the
|
||||
/// specified TagDecl (struct/union/class/enum) decl.
|
||||
QualType ASTContext::getTagDeclType(TagDecl *Decl) {
|
||||
|
|
|
@ -638,6 +638,18 @@ void OCUVectorType::getAsStringInternal(std::string &S) const {
|
|||
ElementType.getAsStringInternal(S);
|
||||
}
|
||||
|
||||
void TypeOfExpr::getAsStringInternal(std::string &InnerString) const {
|
||||
// FIXME: output expression, getUnderlyingExpr()->print().
|
||||
// At the moment, Stmt::print(std::ostream) doesn't work for us here.
|
||||
InnerString = "typeof(<expr>) " + InnerString;
|
||||
}
|
||||
|
||||
void TypeOfType::getAsStringInternal(std::string &S) const {
|
||||
std::string Tmp;
|
||||
getUnderlyingType().getAsStringInternal(Tmp);
|
||||
S += "typeof(" + Tmp + ")";
|
||||
}
|
||||
|
||||
void FunctionTypeNoProto::getAsStringInternal(std::string &S) const {
|
||||
// If needed for precedence reasons, wrap the inner part in grouping parens.
|
||||
if (!S.empty())
|
||||
|
|
|
@ -98,6 +98,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
|
|||
case DeclSpec::TST_union: return "union";
|
||||
case DeclSpec::TST_struct: return "struct";
|
||||
case DeclSpec::TST_typedef: return "typedef";
|
||||
case DeclSpec::TST_typeofType:
|
||||
case DeclSpec::TST_typeofExpr: return "typeof";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -482,6 +482,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
ParseEnumSpecifier(DS);
|
||||
continue;
|
||||
|
||||
// GNU typeof support.
|
||||
case tok::kw_typeof:
|
||||
ParseTypeofSpecifier(DS);
|
||||
continue;
|
||||
|
||||
// type-qualifier
|
||||
case tok::kw_const:
|
||||
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec,
|
||||
|
@ -825,6 +830,9 @@ bool Parser::isTypeSpecifierQualifier() const {
|
|||
default: return false;
|
||||
// GNU attributes support.
|
||||
case tok::kw___attribute:
|
||||
// GNU typeof support.
|
||||
case tok::kw_typeof:
|
||||
|
||||
// type-specifiers
|
||||
case tok::kw_short:
|
||||
case tok::kw_long:
|
||||
|
@ -902,6 +910,9 @@ bool Parser::isDeclarationSpecifier() const {
|
|||
case tok::kw_const:
|
||||
case tok::kw_volatile:
|
||||
case tok::kw_restrict:
|
||||
|
||||
// GNU typeof support.
|
||||
case tok::kw_typeof:
|
||||
|
||||
// function-specifier
|
||||
case tok::kw_inline:
|
||||
|
@ -1397,3 +1408,40 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
|
|||
NumElements.Val, StartLoc));
|
||||
}
|
||||
|
||||
/// [GNU] typeof-specifier:
|
||||
/// typeof ( expressions )
|
||||
/// typeof ( type-name )
|
||||
///
|
||||
void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||
assert(Tok.getKind() == tok::kw_typeof && "Not a typeof specifier");
|
||||
SourceLocation StartLoc = ConsumeToken();
|
||||
|
||||
if (Tok.getKind() != tok::l_paren) {
|
||||
// FIXME: handle error.
|
||||
}
|
||||
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
|
||||
|
||||
if (isTypeSpecifierQualifier()) {
|
||||
TypeTy *Ty = ParseTypeName();
|
||||
|
||||
const char *PrevSpec = 0;
|
||||
bool isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc,
|
||||
PrevSpec, Ty);
|
||||
// FIXME: what we have an invalid type? (or Ty is null)
|
||||
} else { // we have an expression.
|
||||
ExprResult Result = ParseExpression();
|
||||
if (Result.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
}
|
||||
const char *PrevSpec = 0;
|
||||
bool isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc,
|
||||
PrevSpec, Result.Val);
|
||||
// FIXME: what we have an invalid type? (or Result.Val is null)
|
||||
}
|
||||
// Match the ')'.
|
||||
if (Tok.getKind() == tok::r_paren)
|
||||
RParenLoc = ConsumeParen();
|
||||
else
|
||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
}
|
||||
|
||||
|
|
|
@ -1147,7 +1147,7 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
|
|||
result = CheckSingleAssignmentConstraints(lhsType, rex);
|
||||
else
|
||||
result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
|
||||
|
||||
|
||||
// decode the result (notice that extensions still return a type).
|
||||
switch (result) {
|
||||
case Compatible:
|
||||
|
|
|
@ -95,6 +95,18 @@ static QualType ConvertDeclSpecToType(const DeclSpec &DS, ASTContext &Ctx) {
|
|||
// TypeQuals handled by caller.
|
||||
return Ctx.getTypedefType(cast<TypedefDecl>(D));
|
||||
}
|
||||
case DeclSpec::TST_typeofType: {
|
||||
QualType T = QualType::getFromOpaquePtr(DS.getTypeRep());
|
||||
assert(!T.isNull() && "Didn't get a type for typeof?");
|
||||
// TypeQuals handled by caller.
|
||||
return Ctx.getTypeOfType(T);
|
||||
}
|
||||
case DeclSpec::TST_typeofExpr: {
|
||||
Expr *E = static_cast<Expr *>(DS.getTypeRep());
|
||||
assert(E && "Didn't get an expression for typeof?");
|
||||
// TypeQuals handled by caller.
|
||||
return Ctx.getTypeOfType(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@
|
|||
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
|
||||
84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
|
||||
84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
|
||||
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
|
||||
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
|
||||
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
|
||||
|
|
|
@ -100,6 +100,10 @@ public:
|
|||
/// specified typename decl.
|
||||
QualType getTypedefType(TypedefDecl *Decl);
|
||||
|
||||
/// getTypeOfType - GCC extension.
|
||||
QualType getTypeOfType(Expr *e);
|
||||
QualType getTypeOfType(QualType t);
|
||||
|
||||
/// getTagDeclType - Return the unique reference to the type for the
|
||||
/// specified TagDecl (struct/union/class/enum) decl.
|
||||
QualType getTagDeclType(TagDecl *Decl);
|
||||
|
|
|
@ -189,7 +189,8 @@ public:
|
|||
enum TypeClass {
|
||||
Builtin, Complex, Pointer, Reference, Array, Vector, OCUVector,
|
||||
FunctionNoProto, FunctionProto,
|
||||
TypeName, Tagged
|
||||
TypeName, Tagged,
|
||||
TypeOfExp, TypeOfTyp // GNU typeof extension.
|
||||
};
|
||||
private:
|
||||
QualType CanonicalType;
|
||||
|
@ -661,6 +662,37 @@ public:
|
|||
static bool classof(const TypedefType *) { return true; }
|
||||
};
|
||||
|
||||
/// TypeOfExpr (GCC extension).
|
||||
class TypeOfExpr : public Type {
|
||||
Expr *TOExpr;
|
||||
TypeOfExpr(Expr *E, QualType can) : Type(TypeOfExp, can), TOExpr(E) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
Expr *getUnderlyingExpr() const { return TOExpr; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExp; }
|
||||
static bool classof(const TypeOfExpr *) { return true; }
|
||||
};
|
||||
|
||||
/// TypeOfType (GCC extension).
|
||||
class TypeOfType : public Type {
|
||||
QualType TOType;
|
||||
TypeOfType(QualType T, QualType can) : Type(TypeOfTyp, can), TOType(T) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
||||
}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
public:
|
||||
QualType getUnderlyingType() const { return TOType; }
|
||||
|
||||
virtual void getAsStringInternal(std::string &InnerString) const;
|
||||
|
||||
static bool classof(const Type *T) { return T->getTypeClass() == TypeOfTyp; }
|
||||
static bool classof(const TypeOfType *) { return true; }
|
||||
};
|
||||
|
||||
class TagType : public Type {
|
||||
TagDecl *Decl;
|
||||
|
|
|
@ -75,7 +75,9 @@ public:
|
|||
TST_enum,
|
||||
TST_union,
|
||||
TST_struct,
|
||||
TST_typedef
|
||||
TST_typedef,
|
||||
TST_typeofType,
|
||||
TST_typeofExpr
|
||||
};
|
||||
|
||||
// type-qualifiers
|
||||
|
|
|
@ -361,6 +361,7 @@ private:
|
|||
|
||||
TypeTy *ParseTypeName();
|
||||
AttributeList *ParseAttributes();
|
||||
void ParseTypeofSpecifier(DeclSpec &DS);
|
||||
|
||||
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
|
||||
void ParseDeclarator(Declarator &D);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: clang -parse-ast-check %s -pedantic
|
||||
|
||||
typedef int TInt;
|
||||
|
||||
static void test() {
|
||||
int *pi;
|
||||
|
||||
typeof(TInt) anInt; // expected-warning{{extension used}}
|
||||
typeof(const int) aci; // expected-warning{{extension used}}
|
||||
const typeof (*pi) aConstInt; // expected-warning{{extension used}}
|
||||
int xx;
|
||||
short typeof (*pi) aShortInt; // expected-error{{'short typeof' is invalid}}
|
||||
int *i;
|
||||
i = aci; // expected-warning{{incompatible types assigning 'typeof(int const)' to 'int *'}}
|
||||
i = anInt; // expected-warning{{incompatible types assigning 'typeof(TInt)' to 'int *'}}
|
||||
i = aConstInt; // expected-warning{{incompatible types assigning 'typeof(<expr>) const' to 'int *'}}
|
||||
i = xx; // expected-warning{{incompatible types assigning 'int' to 'int *'}}
|
||||
}
|
Loading…
Reference in New Issue