diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -1531,7 +1531,12 @@ */ CXCursor_RequiresExpr = 154, - CXCursor_LastExpr = CXCursor_RequiresExpr, + /** + * A clang-builtin of unspecified value. + */ + CXCursor_UnspecifiedValueExpr = 155, + + CXCursor_LastExpr = CXCursor_UnspecifiedValueExpr, /* Statements */ CXCursor_FirstStmt = 200, diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4634,6 +4634,43 @@ } }; +/// UnspecifiedValueExpr - clang-specific value __builtin_unspecified_value. +/// This AST node represents freeze(poison) in LLVM IR. +class UnspecifiedValueExpr : public Expr { + /// TokenLoc - The location of the __builtin_specified_value keyword. + SourceLocation TokenLoc; + +public: + UnspecifiedValueExpr(QualType Ty, SourceLocation Loc) + : Expr(UnspecifiedValueExprClass, Ty, VK_PRValue, OK_Ordinary), + TokenLoc(Loc) { + setDependence(ExprDependence::None); + } + + /// Build an empty GNU __null expression. + explicit UnspecifiedValueExpr(EmptyShell Empty) : + Expr(UnspecifiedValueExprClass, Empty) { } + + /// getTokenLocation - The location of the __null token. + SourceLocation getTokenLocation() const { return TokenLoc; } + void setTokenLocation(SourceLocation L) { TokenLoc = L; } + + SourceLocation getBeginLoc() const LLVM_READONLY { return TokenLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return TokenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnspecifiedValueExprClass; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + /// Represents a call to the builtin function \c __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2797,6 +2797,7 @@ DEF_TRAVERSE_STMT(ConvertVectorExpr, {}) DEF_TRAVERSE_STMT(StmtExpr, {}) DEF_TRAVERSE_STMT(SourceLocExpr, {}) +DEF_TRAVERSE_STMT(UnspecifiedValueExpr, {}) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -202,6 +202,7 @@ def TypoExpr : StmtNode; def RecoveryExpr : StmtNode; def BuiltinBitCastExpr : StmtNode; +def UnspecifiedValueExpr : StmtNode; // Microsoft Extensions. def MSPropertyRefExpr : StmtNode; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1706,6 +1706,9 @@ /// A GNUNullExpr record. EXPR_GNU_NULL, + // An UnspecifiedValueExpr record. + EXPR_UNSPECIFIED_VALUE, + /// A SourceLocExpr record. EXPR_SOURCE_LOC, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -618,6 +618,7 @@ ExpectedStmt VisitChooseExpr(ChooseExpr *E); ExpectedStmt VisitShuffleVectorExpr(ShuffleVectorExpr *E); ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E); + ExpectedStmt VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E); ExpectedStmt VisitGenericSelectionExpr(GenericSelectionExpr *E); ExpectedStmt VisitPredefinedExpr(PredefinedExpr *E); ExpectedStmt VisitDeclRefExpr(DeclRefExpr *E); @@ -6987,6 +6988,20 @@ return new (Importer.getToContext()) GNUNullExpr(*TypeOrErr, *BeginLocOrErr); } +ExpectedStmt ASTNodeImporter::VisitUnspecifiedValueExpr( + UnspecifiedValueExpr *E) { + ExpectedType TypeOrErr = import(E->getType()); + if (!TypeOrErr) + return TypeOrErr.takeError(); + + ExpectedSLoc BeginLocOrErr = import(E->getBeginLoc()); + if (!BeginLocOrErr) + return BeginLocOrErr.takeError(); + + return new (Importer.getToContext()) UnspecifiedValueExpr(*TypeOrErr, + *BeginLocOrErr); +} + ExpectedStmt ASTNodeImporter::VisitGenericSelectionExpr(GenericSelectionExpr *E) { Error Err = Error::success(); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3638,6 +3638,7 @@ case SubstNonTypeTemplateParmExprClass: case MaterializeTemporaryExprClass: case ShuffleVectorExprClass: + case UnspecifiedValueExprClass: case ConvertVectorExprClass: case AsTypeExprClass: // These have a side-effect if any subexpression does. diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -167,6 +167,7 @@ case Expr::OffsetOfExprClass: case Expr::CXXThrowExprClass: case Expr::ShuffleVectorExprClass: + case Expr::UnspecifiedValueExprClass: case Expr::ConvertVectorExprClass: case Expr::IntegerLiteralClass: case Expr::FixedPointLiteralClass: diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1674,6 +1674,10 @@ OS << "__null"; } +void StmtPrinter::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *) { + OS << "__builtin_unspecified_value"; +} + void StmtPrinter::VisitShuffleVectorExpr(ShuffleVectorExpr *Node) { OS << "__builtin_shufflevector("; for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1472,6 +1472,10 @@ VisitExpr(S); } +void StmtProfiler::VisitUnspecifiedValueExpr(const UnspecifiedValueExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitVAArgExpr(const VAArgExpr *S) { VisitExpr(S); } diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1404,6 +1404,7 @@ case Expr::SourceLocExprClass: case Expr::ConceptSpecializationExprClass: case Expr::RequiresExprClass: + case Expr::UnspecifiedValueExprClass: // These expressions can never throw. return CT_Cannot; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -11719,6 +11719,12 @@ return E; } +template +ExprResult +TreeTransform::TransformUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + return E; +} + template ExprResult TreeTransform::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1316,6 +1316,11 @@ E->setTokenLocation(readSourceLocation()); } +void ASTStmtReader::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + VisitExpr(E); + E->setTokenLocation(readSourceLocation()); +} + void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); SmallVector Exprs; @@ -3077,6 +3082,10 @@ S = new (Context) GNUNullExpr(Empty); break; + case EXPR_UNSPECIFIED_VALUE: + S = new (Context) UnspecifiedValueExpr(Empty); + break; + case EXPR_SHUFFLE_VECTOR: S = new (Context) ShuffleVectorExpr(Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1195,6 +1195,12 @@ Code = serialization::EXPR_GNU_NULL; } +void ASTStmtWriter::VisitUnspecifiedValueExpr(UnspecifiedValueExpr *E) { + VisitExpr(E); + Record.AddSourceLocation(E->getTokenLocation()); + Code = serialization::EXPR_UNSPECIFIED_VALUE; +} + void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); Record.push_back(E->getNumSubExprs()); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1889,6 +1889,7 @@ case Stmt::ObjCSelectorExprClass: case Stmt::ParenListExprClass: case Stmt::ShuffleVectorExprClass: + case Stmt::UnspecifiedValueExprClass: case Stmt::ConvertVectorExprClass: case Stmt::VAArgExprClass: case Stmt::CUDAKernelCallExprClass: diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -475,6 +475,10 @@ K = CXCursor_GNUNullExpr; break; + case Stmt::UnspecifiedValueExprClass: + K = CXCursor_UnspecifiedValueExpr; + break; + case Stmt::CXXStaticCastExprClass: K = CXCursor_CXXStaticCastExpr; break;