[cfe-commits] r40631 - in /cfe/trunk: AST/ASTContext.cpp AST/Type.cpp Parse/DeclSpec.cpp Parse/ParseDecl.cpp Sema/SemaExpr.cpp Sema/SemaType.cpp clang.xcodeproj/project.pbxproj include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h test/Parser/typeof.c

Steve Naroff snaroff at apple.com
Tue Jul 31 05:34:37 PDT 2007


Author: snaroff
Date: Tue Jul 31 07:34:36 2007
New Revision: 40631

URL: http://llvm.org/viewvc/llvm-project?rev=40631&view=rev
Log:

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.


Added:
    cfe/trunk/test/Parser/typeof.c
Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Type.cpp
    cfe/trunk/Parse/DeclSpec.cpp
    cfe/trunk/Parse/ParseDecl.cpp
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/Sema/SemaType.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Tue Jul 31 07:34:36 2007
@@ -584,6 +584,18 @@
   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) {

Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Tue Jul 31 07:34:36 2007
@@ -638,6 +638,18 @@
   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())

Modified: cfe/trunk/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/DeclSpec.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/Parse/DeclSpec.cpp Tue Jul 31 07:34:36 2007
@@ -98,6 +98,8 @@
   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";
   }
 }
 

Modified: cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseDecl.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/Parse/ParseDecl.cpp Tue Jul 31 07:34:36 2007
@@ -482,6 +482,11 @@
       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 @@
   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 @@
   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 @@
                                           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);
+}
+

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Tue Jul 31 07:34:36 2007
@@ -1147,7 +1147,7 @@
     result = CheckSingleAssignmentConstraints(lhsType, rex);
   else
     result = CheckCompoundAssignmentConstraints(lhsType, rhsType);
-    
+
   // decode the result (notice that extensions still return a type).
   switch (result) {
   case Compatible:

Modified: cfe/trunk/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaType.cpp?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaType.cpp (original)
+++ cfe/trunk/Sema/SemaType.cpp Tue Jul 31 07:34:36 2007
@@ -95,6 +95,18 @@
     // 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);
+  }
   }
 }
 

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Tue Jul 31 07:34:36 2007
@@ -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>"; };

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Jul 31 07:34:36 2007
@@ -100,6 +100,10 @@
   /// 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);

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Jul 31 07:34:36 2007
@@ -189,7 +189,8 @@
   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 @@
   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;

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Tue Jul 31 07:34:36 2007
@@ -75,7 +75,9 @@
     TST_enum,
     TST_union,
     TST_struct,
-    TST_typedef
+    TST_typedef,
+    TST_typeofType,
+    TST_typeofExpr
   };
   
   // type-qualifiers

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=40631&r1=40630&r2=40631&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Jul 31 07:34:36 2007
@@ -361,6 +361,7 @@
 
   TypeTy *ParseTypeName();
   AttributeList *ParseAttributes();
+  void ParseTypeofSpecifier(DeclSpec &DS);
   
   /// ParseDeclarator - Parse and verify a newly-initialized declarator.
   void ParseDeclarator(Declarator &D);

Added: cfe/trunk/test/Parser/typeof.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/typeof.c?rev=40631&view=auto

==============================================================================
--- cfe/trunk/test/Parser/typeof.c (added)
+++ cfe/trunk/test/Parser/typeof.c Tue Jul 31 07:34:36 2007
@@ -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 *'}}
+}





More information about the cfe-commits mailing list