aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@boostpro.com>2011-04-25 06:54:41 +0000
committerJohn Wiegley <johnw@boostpro.com>2011-04-25 06:54:41 +0000
commit552622067dc45013d240f73952fece703f5e63bd (patch)
tree05c7abd4e26f18ecddc4d05de7dd30af3408fa7e /lib
parent62395c9666b84bcb0cb322d5f5183472712685f6 (diff)
t/clang/expr-traits
Patch authored by David Abrahams. These two expression traits (__is_lvalue_expr, __is_rvalue_expr) are used for parsing code that employs certain features of the Embarcadero C++ compiler. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130122 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ExprClassification.cpp1
-rw-r--r--lib/AST/ExprConstant.cpp5
-rw-r--r--lib/AST/ItaniumMangle.cpp1
-rw-r--r--lib/AST/StmtPrinter.cpp15
-rw-r--r--lib/AST/StmtProfile.cpp6
-rw-r--r--lib/CodeGen/CGExprScalar.cpp4
-rw-r--r--lib/Parse/ParseExpr.cpp8
-rw-r--r--lib/Parse/ParseExprCXX.cpp30
-rw-r--r--lib/Sema/SemaExprCXX.cpp39
-rw-r--r--lib/Sema/TreeTransform.h29
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp15
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
13 files changed, 164 insertions, 0 deletions
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 0d01880414..ebbdf94f10 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -152,6 +152,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CXXScalarValueInitExprClass:
case Expr::UnaryTypeTraitExprClass:
case Expr::BinaryTypeTraitExprClass:
+ case Expr::ExpressionTraitExprClass:
case Expr::ObjCSelectorExprClass:
case Expr::ObjCProtocolExprClass:
case Expr::ObjCStringLiteralClass:
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index e738f0dc90..519bbaa115 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1061,6 +1061,10 @@ public:
return Success(E->getValue(), E);
}
+ bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
+ return Success(E->getValue(), E);
+ }
+
bool VisitChooseExpr(const ChooseExpr *E) {
return Visit(E->getChosenSubExpr(Info.Ctx));
}
@@ -2875,6 +2879,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXScalarValueInitExprClass:
case Expr::UnaryTypeTraitExprClass:
case Expr::BinaryTypeTraitExprClass:
+ case Expr::ExpressionTraitExprClass:
case Expr::CXXNoexceptExprClass:
return NoDiag();
case Expr::CallExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index a32b0ef751..b62442d6d2 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1910,6 +1910,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::StmtExprClass:
case Expr::UnaryTypeTraitExprClass:
case Expr::BinaryTypeTraitExprClass:
+ case Expr::ExpressionTraitExprClass:
case Expr::VAArgExprClass:
case Expr::CXXUuidofExprClass:
case Expr::CXXNoexceptExprClass:
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 3591c32ad8..cf42e63379 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1281,6 +1281,15 @@ static const char *getTypeTraitName(BinaryTypeTrait BTT) {
return "";
}
+static const char *getExpressionTraitName(ExpressionTrait ET) {
+ switch (ET) {
+ default: llvm_unreachable("Unknown expression trait");
+ case ET_IsLValueExpr: return "__is_lvalue_expr";
+ case ET_IsRValueExpr: return "__is_rvalue_expr";
+ }
+ return "";
+}
+
void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
OS << getTypeTraitName(E->getTrait()) << "("
<< E->getQueriedType().getAsString(Policy) << ")";
@@ -1292,6 +1301,12 @@ void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
<< E->getRhsType().getAsString(Policy) << ")";
}
+void StmtPrinter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ OS << getExpressionTraitName(E->getTrait()) << "(";
+ PrintExpr(E->getQueriedExpression());
+ OS << ")";
+}
+
void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
OS << "noexcept(";
PrintExpr(E->getOperand());
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index dbcb7e4fe6..fe9a10b01e 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -802,6 +802,12 @@ void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
VisitType(S->getRhsType());
}
+void StmtProfiler::VisitExpressionTraitExpr(ExpressionTraitExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getTrait());
+ VisitExpr(S->getQueriedExpression());
+}
+
void
StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
VisitExpr(S);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 6c5556d4f1..f6de1fa127 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -367,6 +367,10 @@ public:
return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
}
+ Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
+ return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
+ }
+
Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
// C++ [expr.pseudo]p1:
// The result shall only be used as the operand for the function call
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index cd8f9c53f7..12761e8d9f 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -555,6 +555,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// [GNU] '__is_base_of'
/// [MS] '__is_convertible_to'
///
+/// [Embarcadero] expression-trait:
+/// '__is_lvalue_expr'
+/// '__is_rvalue_expr'
+///
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
@@ -1021,6 +1025,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_convertible_to:
return ParseBinaryTypeTrait();
+ case tok::kw___is_lvalue_expr:
+ case tok::kw___is_rvalue_expr:
+ return ParseExpressionTrait();
+
case tok::at: {
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1165ff0978..e6abac3b4c 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1944,6 +1944,14 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
}
}
+static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) {
+ switch(kind) {
+ default: assert(false && "Not a known unary expression trait.");
+ case tok::kw___is_lvalue_expr: return ET_IsLValueExpr;
+ case tok::kw___is_rvalue_expr: return ET_IsRValueExpr;
+ }
+}
+
/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
/// pseudo-functions that allow implementation of the TR1/C++0x type traits
/// templates.
@@ -2009,6 +2017,28 @@ ExprResult Parser::ParseBinaryTypeTrait() {
return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen);
}
+/// ParseExpressionTrait - Parse built-in expression-trait
+/// pseudo-functions like __is_lvalue_expr( xxx ).
+///
+/// primary-expression:
+/// [Embarcadero] expression-trait '(' expression ')'
+///
+ExprResult Parser::ParseExpressionTrait() {
+ ExpressionTrait ET = ExpressionTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ ExprResult Expr = ParseExpression();
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ return Actions.ActOnExpressionTrait(ET, Loc, Expr.get(), RParen);
+}
+
+
/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
/// based on the context past the parens.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 27545d802e..edfa4a532d 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2739,6 +2739,45 @@ ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT,
ResultType));
}
+ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET,
+ SourceLocation KWLoc,
+ Expr* Queried,
+ SourceLocation RParen) {
+ // If error parsing the expression, ignore.
+ if (!Queried)
+ return ExprError();
+
+ ExprResult Result
+ = BuildExpressionTrait(ET, KWLoc, Queried, RParen);
+
+ return move(Result);
+}
+
+ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET,
+ SourceLocation KWLoc,
+ Expr* Queried,
+ SourceLocation RParen) {
+ if (Queried->isTypeDependent()) {
+ // Delay type-checking for type-dependent expressions.
+ } else if (Queried->getType()->isPlaceholderType()) {
+ ExprResult PE = CheckPlaceholderExpr(Queried);
+ if (PE.isInvalid()) return ExprError();
+ return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen);
+ }
+
+ bool Value = false;
+ switch (ET) {
+ default: llvm_unreachable("Unknown or unimplemented expression trait");
+ case ET_IsLValueExpr: Value = Queried->isLValue(); break;
+ case ET_IsRValueExpr: Value = Queried->isRValue(); break;
+ }
+
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Owned(
+ new (Context) ExpressionTraitExpr(
+ KWLoc, ET, Queried, Value, RParen, Context.BoolTy));
+}
+
QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
ExprValueKind &VK,
SourceLocation Loc,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index dc96e59420..c642e642cc 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1915,6 +1915,17 @@ public:
return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
}
+ /// \brief Build a new expression trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildExpressionTrait(ExpressionTrait Trait,
+ SourceLocation StartLoc,
+ Expr *Queried,
+ SourceLocation RParenLoc) {
+ return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc);
+ }
+
/// \brief Build a new (previously unresolved) declaration reference
/// expression.
///
@@ -6911,6 +6922,24 @@ TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) {
+ ExprResult SubExpr;
+ {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
+ SubExpr = getDerived().TransformExpr(E->getQueriedExpression());
+ if (SubExpr.isInvalid())
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression())
+ return SemaRef.Owned(E);
+ }
+
+ return getDerived().RebuildExpressionTrait(
+ E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
NestedNameSpecifierLoc QualifierLoc
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 07c5c7b804..608aafc3ce 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -179,6 +179,7 @@ namespace clang {
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
void VisitPackExpansionExpr(PackExpansionExpr *E);
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
@@ -1343,6 +1344,16 @@ void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
E->RhsType = GetTypeSourceInfo(Record, Idx);
}
+void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ VisitExpr(E);
+ E->ET = (ExpressionTrait)Record[Idx++];
+ E->Value = (bool)Record[Idx++];
+ SourceRange Range = ReadSourceRange(Record, Idx);
+ E->QueriedExpression = Reader.ReadSubExpr();
+ E->Loc = Range.getBegin();
+ E->RParen = Range.getEnd();
+}
+
void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
E->Value = (bool)Record[Idx++];
@@ -1935,6 +1946,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
S = new (Context) BinaryTypeTraitExpr(Empty);
break;
+ case EXPR_CXX_EXPRESSION_TRAIT:
+ S = new (Context) ExpressionTraitExpr(Empty);
+ break;
+
case EXPR_CXX_NOEXCEPT:
S = new (Context) CXXNoexceptExpr(Empty);
break;
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index c2b038284c..19cd834dd4 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -153,6 +153,7 @@ namespace clang {
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+ void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
void VisitPackExpansionExpr(PackExpansionExpr *E);
void VisitSizeOfPackExpr(SizeOfPackExpr *E);
@@ -1339,6 +1340,15 @@ void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
Code = serialization::EXPR_BINARY_TYPE_TRAIT;
}
+void ASTStmtWriter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getTrait());
+ Record.push_back(E->getValue());
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ Writer.AddStmt(E->getQueriedExpression());
+ Code = serialization::EXPR_CXX_EXPRESSION_TRAIT;
+}
+
void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
Record.push_back(E->getValue());
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index ac7e687b93..49af4304b0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -435,6 +435,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::UnaryTypeTraitExprClass:
case Stmt::BinaryTypeTraitExprClass:
+ case Stmt::ExpressionTraitExprClass:
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnresolvedMemberExprClass:
case Stmt::CXXNoexceptExprClass: