diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 35 | ||||
| -rw-r--r-- | clang/include/clang/AST/StmtNodes.def | 1 | ||||
| -rw-r--r-- | clang/include/clang/Parse/Action.h | 6 | ||||
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 12 | 
9 files changed, 89 insertions, 2 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 321dca53365..dfdca82c746 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -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.  /// diff --git a/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index 06e5419d9e5..0c7faff1eda 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/include/clang/AST/StmtNodes.def @@ -88,6 +88,7 @@ STMT(AddrLabelExpr        , Expr)  STMT(StmtExpr             , Expr)  STMT(TypesCompatibleExpr  , Expr)  STMT(ChooseExpr           , Expr) +STMT(GNUNullExpr          , Expr)  // C++ Expressions.  STMT(CXXOperatorCallExpr    , CallExpr) diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index e32dc388fc7..cf18b6250db 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -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 diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 7a8119c5e3d..3c021c262d6 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -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; } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index fcebdab05c6..b6f07070538 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -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) { diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index 8bf70396856..3cf1f5497fb 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -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); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 66b1d180780..df46612b57d 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -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(); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 57caa6ecf24..044bfbd73be 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e21047e10d8..fb964692b35 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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,  | 

