Add AST/Sema support for __builtin_types_compatible_p (a GNU extension).
Todo...still need to call the action from the parser...


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40693 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index 18f605b..9ca1783 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -481,6 +481,12 @@
   OS << ")";
 }
 
+void StmtPrinter::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
+  OS << "__builtin_types_compatible_p(";
+  OS << Node->getArgType1().getAsString() << ",";
+  OS << Node->getArgType2().getAsString() << ")";
+}
+
 
 // C++
 
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
index de0a2a2..15aca62 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -819,12 +819,12 @@
     Res = ParseAssignmentExpression();
     break;
   case tok::kw___builtin_types_compatible_p:
-    ParseTypeName();
+    TypeTy *Type1 = ParseTypeName();
     
     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
       return ExprResult(true);
     
-    ParseTypeName();
+    TypeTy *Type2 = ParseTypeName();
     break;
   }      
   
diff --git a/Sema/Sema.h b/Sema/Sema.h
index ea724ab..86378a4 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -280,6 +280,11 @@
   
   virtual ExprResult ParseStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt,
                                    SourceLocation RPLoc); // "({..})"
+                                   
+  // __builtin_types_compatible_p(type1, type2)
+  virtual ExprResult ParseTypesCompatibleExpr(SourceLocation LPLoc, 
+                                              TypeTy *arg1, TypeTy *arg2,
+                                              SourceLocation RPLoc);
   
   /// ParseCXXCasts - Parse {dynamic,static,reinterpret,const}_cast's.
   virtual ExprResult ParseCXXCasts(SourceLocation OpLoc, tok::TokenKind Kind,
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 1570f4a..9ef2e67 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1565,3 +1565,15 @@
   
   return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
 }
+
+Sema::ExprResult Sema::ParseTypesCompatibleExpr(SourceLocation LPLoc, 
+                                                TypeTy *arg1, TypeTy *arg2,
+                                                SourceLocation RPLoc) {
+  QualType argT1 = QualType::getFromOpaquePtr(arg1);
+  QualType argT2 = QualType::getFromOpaquePtr(arg2);
+  
+  assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
+  
+  return new TypesCompatibleExpr(Context.IntTy, LPLoc, argT1, argT2, RPLoc);
+}
+
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 01917dc..568d3e0 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -703,10 +703,9 @@
   CompoundStmt *SubStmt;
   SourceLocation LParenLoc, RParenLoc;
 public:
-    StmtExpr(CompoundStmt *substmt, QualType T,
-             SourceLocation lp, SourceLocation rp)
-    : Expr(StmtExprClass, T), SubStmt(substmt),  LParenLoc(lp), RParenLoc(rp) {
-    }
+  StmtExpr(CompoundStmt *substmt, QualType T,
+           SourceLocation lp, SourceLocation rp) :
+    Expr(StmtExprClass, T), SubStmt(substmt),  LParenLoc(lp), RParenLoc(rp) { }
   
   CompoundStmt *getSubStmt() { return SubStmt; }
   const CompoundStmt *getSubStmt() const { return SubStmt; }
@@ -722,6 +721,33 @@
   static bool classof(const StmtExpr *) { return true; }
 };
 
+/// TypesCompatibleExpr - GNU builtin-in function __builtin_type_compatible_p.
+/// This AST node represents a function that returns 1 if two *types* (not
+/// expressions) are compatible. The result of this built-in function can be
+/// used in integer constant expressions.
+class TypesCompatibleExpr : public Expr {
+  QualType Type1;
+  QualType Type2;
+  SourceLocation LParenLoc, RParenLoc;
+public:
+  TypesCompatibleExpr(QualType ReturnType, SourceLocation LP, 
+                      QualType t1, QualType t2, SourceLocation RP) : 
+    Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2),
+    LParenLoc(LP), RParenLoc(RP) {}
+
+  QualType getArgType1() { return Type1; }
+  QualType getArgType2() { return Type2; }
+    
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(LParenLoc, RParenLoc);
+  }
+  virtual void visit(StmtVisitor &Visitor);
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == TypesCompatibleExprClass; 
+  }
+  static bool classof(const TypesCompatibleExpr *) { return true; }
+};
+
 }  // end namespace clang
 
 #endif
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 4335b51..375a52b 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -67,11 +67,12 @@
 // GNU Extensions.
 STMT(50, AddrLabel            , Expr)
 STMT(51, StmtExpr             , Expr)
+STMT(52, TypesCompatibleExpr  , Expr)
 
 // C++ Expressions.
-STMT(52, CXXCastExpr          , Expr)
-STMT(53, CXXBoolLiteralExpr   , Expr)
-LAST_EXPR(53)
+STMT(53, CXXCastExpr          , Expr)
+STMT(54, CXXBoolLiteralExpr   , Expr)
+LAST_EXPR(54)
 
 #undef STMT
 #undef FIRST_STMT
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index d9e3e12..c019a0b 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -375,6 +375,12 @@
                                    SourceLocation RPLoc) { // "({..})"
     return 0;
   }
+  // __builtin_types_compatible_p(type1, type2)
+  virtual ExprResult ParseTypesCompatibleExpr(SourceLocation LPLoc, 
+                                              TypeTy *arg1, TypeTy *arg2,
+                                              SourceLocation RPLoc) {
+    return 0;
+  }
 
   //===------------------------- C++ Expressions --------------------------===//