]> granicus.if.org Git - clang/commitdiff
Implement the GNU __null extension
authorDouglas Gregor <dgregor@apple.com>
Sat, 29 Nov 2008 04:51:27 +0000 (04:51 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 29 Nov 2008 04:51:27 +0000 (04:51 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60235 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/AST/StmtNodes.def
include/clang/Parse/Action.h
lib/AST/Expr.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtSerialization.cpp
lib/Parse/ParseExpr.cpp
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp

index 321dca5336585baf5959ee745bd78325b9bb07d3..dfdca82c746f0cab15c73d21b939b3bbb20e0ec5 100644 (file)
@@ -1295,7 +1295,7 @@ public:
 /// ChooseExpr - GNU builtin-in function __builtin_choose_expr.
 /// This AST node is similar to the conditional operator (?:) in C, with 
 /// the following exceptions:
-/// - the test expression much be a constant expression.
+/// - the test expression must be a constant expression.
 /// - the expression returned has it's type unaltered by promotion rules.
 /// - does not evaluate the expression that was not chosen.
 class ChooseExpr : public Expr {
@@ -1336,6 +1336,39 @@ public:
   static ChooseExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// GNUNullExpr - Implements the GNU __null extension, which is a name
+/// for a null pointer constant that has integral type (e.g., int or
+/// long) and is the same size and alignment as a pointer. The __null
+/// extension is typically only used by system headers, which define
+/// NULL as __null in C++ rather than using 0 (which is an integer
+/// that may not match the size of a pointer).
+class GNUNullExpr : public Expr {
+  /// TokenLoc - The location of the __null keyword.
+  SourceLocation TokenLoc;
+
+public:
+  GNUNullExpr(QualType Ty, SourceLocation Loc) 
+    : Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { }
+
+  /// getTokenLocation - The location of the __null token.
+  SourceLocation getTokenLocation() const { return TokenLoc; }
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(TokenLoc);
+  }
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == GNUNullExprClass; 
+  }
+  static bool classof(const GNUNullExpr *) { return true; }
+  
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static GNUNullExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);  
+};
+
 /// OverloadExpr - Clang builtin function __builtin_overload.
 /// This AST node provides a way to overload functions in C.
 ///
index 06e5419d9e5a9dd9fe6797e99fee443db06a302e..0c7faff1eda77cd31645471e7ee94e31cb5f95ce 100644 (file)
@@ -88,6 +88,7 @@ STMT(AddrLabelExpr        , Expr)
 STMT(StmtExpr             , Expr)
 STMT(TypesCompatibleExpr  , Expr)
 STMT(ChooseExpr           , Expr)
+STMT(GNUNullExpr          , Expr)
 
 // C++ Expressions.
 STMT(CXXOperatorCallExpr    , CallExpr)
index e32dc388fc74329bb4a82b88e4097c52f98f0c6a..cf18b6250dbde7a2d855ad15b36c9a112e1e670a 100644 (file)
@@ -638,6 +638,12 @@ public:
     return 0;
   }
 
+  /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token
+  /// for which is at position TokenLoc.
+  virtual ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
+    return 0;
+  }
+
   //===------------------------- "Block" Extension ------------------------===//
 
   /// ActOnBlockStart - This callback is invoked when a block literal is
index 7a8119c5e3d1f8ae281ee6771a8f5bd89aebf42f..3c021c262d66fed1cf739a700a1d2113490bfb7e 100644 (file)
@@ -1031,8 +1031,11 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const {
                = dyn_cast<CXXDefaultArgExpr>(this)) {
     // See through default argument expressions
     return DefaultArg->getExpr()->isNullPointerConstant(Ctx);
+  } else if (isa<GNUNullExpr>(this)) {
+    // The GNU __null extension is always a null pointer constant.
+    return true;
   }
-  
+
   // This expression must be an integer type.
   if (!getType()->isIntegerType())
     return false;
@@ -1383,6 +1386,10 @@ Stmt::child_iterator TypesCompatibleExpr::child_end() {
 Stmt::child_iterator ChooseExpr::child_begin() { return &SubExprs[0]; }
 Stmt::child_iterator ChooseExpr::child_end() { return &SubExprs[0]+END_EXPR; }
 
+// GNUNullExpr
+Stmt::child_iterator GNUNullExpr::child_begin() { return child_iterator(); }
+Stmt::child_iterator GNUNullExpr::child_end() { return child_iterator(); }
+
 // OverloadExpr
 Stmt::child_iterator OverloadExpr::child_begin() { return &SubExprs[0]; }
 Stmt::child_iterator OverloadExpr::child_end() { return &SubExprs[0]+NumExprs; }
index fcebdab05c65691afa29d9eddb691b2c44912345..b6f07070538f4ad558ead6b54d0edc1750394c9f 100644 (file)
@@ -783,6 +783,10 @@ void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
   OS << ")";
 }
 
+void StmtPrinter::VisitGNUNullExpr(GNUNullExpr *) {
+  OS << "__null";
+}
+
 void StmtPrinter::VisitOverloadExpr(OverloadExpr *Node) {
   OS << "__builtin_overload(";
   for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
index 8bf70396856abaddb5ac9387a7550fb60043683a..3cf1f5497fbd8fd99cd3b154d5c1f3520dbd3df8 100644 (file)
@@ -61,6 +61,9 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
     case CharacterLiteralClass:
       return CharacterLiteral::CreateImpl(D, C);
       
+    case ChooseExprClass:
+      return ChooseExpr::CreateImpl(D, C);
+
     case CompoundAssignOperatorClass:
       return CompoundAssignOperator::CreateImpl(D, C);
       
@@ -94,6 +97,9 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) {
     case ForStmtClass:
       return ForStmt::CreateImpl(D, C);
     
+    case GNUNullExprClass:
+      return GNUNullExpr::CreateImpl(D, C);
+
     case GotoStmtClass:
       return GotoStmt::CreateImpl(D, C);
       
@@ -904,6 +910,17 @@ ChooseExpr* ChooseExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
   return CE;
 }
 
+void GNUNullExpr::EmitImpl(llvm::Serializer &S) const {
+  S.Emit(getType());
+  S.Emit(TokenLoc);
+}
+
+GNUNullExpr *GNUNullExpr::CreateImpl(llvm::Deserializer &D, ASTContext &C) {
+  QualType T = QualType::ReadVal(D);
+  SourceLocation TL = SourceLocation::ReadVal(D);
+  return new GNUNullExpr(T, TL);
+}
+
 void OverloadExpr::EmitImpl(llvm::Serializer& S) const {
   S.Emit(getType());
   S.Emit(BuiltinLoc);
index 66b1d180780b83648ac191aa5c724ffffc65d91a..df46612b57ddfffb881d01eeba46806ecf5953b7 100644 (file)
@@ -378,6 +378,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
 /// [GNU]   '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
 ///                                     assign-expr ')'
 /// [GNU]   '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
+/// [GNU]   '__null'
 /// [OBJC]  '[' objc-message-expr ']'    
 /// [OBJC]  '@selector' '(' objc-selector-arg ')'
 /// [OBJC]  '@protocol' '(' identifier ')'             
@@ -531,6 +532,9 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
   case tok::kw___builtin_overload:
   case tok::kw___builtin_types_compatible_p:
     return ParseBuiltinPrimaryExpression();
+  case tok::kw___null:
+    return Actions.ActOnGNUNullExpr(ConsumeToken());
+    break;
   case tok::plusplus:      // unary-expression: '++' unary-expression
   case tok::minusminus: {  // unary-expression: '--' unary-expression
     SourceLocation SavedLoc = ConsumeToken();
index 57caa6ecf24e8f06a58b4ea46eef82de9b2b1428..044bfbd73be1bb79964c71e5d6257ac8a390333d 100644 (file)
@@ -736,6 +736,9 @@ public:
                                 ExprTy *expr, TypeTy *type,
                                 SourceLocation RPLoc);
 
+  // __null
+  virtual ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
   //===------------------------- "Block" Extension ------------------------===//
 
   /// ActOnBlockStart - This callback is invoked when a block literal is
index e21047e10d8f2c65f068426e45d249a663c989c4..fb964692b3530d51fbc76e0093ac9785c0a79ed5 100644 (file)
@@ -3603,6 +3603,18 @@ Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
   return new VAArgExpr(BuiltinLoc, E, T.getNonReferenceType(), RPLoc);
 }
 
+Sema::ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
+  // The type of __null will be int or long, depending on the size of
+  // pointers on the target.
+  QualType Ty;
+  if (Context.Target.getPointerWidth(0) == Context.Target.getIntWidth())
+    Ty = Context.IntTy;
+  else
+    Ty = Context.LongTy;
+
+  return new GNUNullExpr(Ty, TokenLoc);
+}
+
 bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
                                     SourceLocation Loc,
                                     QualType DstType, QualType SrcType,