diff options
author | Francois Pichet <pichet2000@gmail.com> | 2010-09-08 12:20:18 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2010-09-08 12:20:18 +0000 |
commit | 01b7c3028da5bbcb9f8e52ba67e4613070de0e60 (patch) | |
tree | 5f6b37f01f1f28b36b43f6ba76a4a50f69cd14d5 /lib | |
parent | 538e0d0292cab16198a4fce5c388ff06adc74d0c (diff) |
Microsoft's __uuidof operator implementation part 1.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113356 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 16 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 10 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 56 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 63 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 19 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 13 |
10 files changed, 235 insertions, 1 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 8caf70b3e1..f72ab98eb8 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -39,6 +39,22 @@ Stmt::child_iterator CXXTypeidExpr::child_end() { : reinterpret_cast<Stmt **>(&Operand) + 1; } +QualType CXXUuidofExpr::getTypeOperand() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); + return Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType() + .getUnqualifiedType(); +} + +// CXXUuidofExpr - has child iterators if the operand is an expression +Stmt::child_iterator CXXUuidofExpr::child_begin() { + return isTypeOperand() ? child_iterator() + : reinterpret_cast<Stmt **>(&Operand); +} +Stmt::child_iterator CXXUuidofExpr::child_end() { + return isTypeOperand() ? child_iterator() + : reinterpret_cast<Stmt **>(&Operand) + 1; +} + // CXXBoolLiteralExpr Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { return child_iterator(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 1778ce84d1..88e047ddc3 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1002,6 +1002,16 @@ void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) { OS << ")"; } +void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { + OS << "__uuidof("; + if (Node->isTypeOperand()) { + OS << Node->getTypeOperand().getAsString(Policy); + } else { + PrintExpr(Node->getExprOperand()); + } + OS << ")"; +} + void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { OS << (Node->getValue() ? "true" : "false"); } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 78a336d2bf..843248cc0b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -687,6 +687,12 @@ void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) { VisitType(S->getTypeOperand()); } +void StmtProfiler::VisitCXXUuidofExpr(CXXUuidofExpr *S) { + VisitExpr(S); + if (S->isTypeOperand()) + VisitType(S->getTypeOperand()); +} + void StmtProfiler::VisitCXXThisExpr(CXXThisExpr *S) { VisitExpr(S); } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index c4beab191d..6a7c72304c 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -768,6 +768,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_typeid: Res = ParseCXXTypeid(); break; + case tok::kw___uuidof: + Res = ParseCXXUuidof(); + break; case tok::kw_this: Res = ParseCXXThis(); break; diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index c48ae7ccc1..18259ceb78 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -534,6 +534,54 @@ ExprResult Parser::ParseCXXTypeid() { return move(Result); } +/// ParseCXXUuidof - This handles the Microsoft C++ __uuidof expression. +/// +/// '__uuidof' '(' expression ')' +/// '__uuidof' '(' type-id ')' +/// +ExprResult Parser::ParseCXXUuidof() { + assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!"); + + SourceLocation OpLoc = ConsumeToken(); + SourceLocation LParenLoc = Tok.getLocation(); + SourceLocation RParenLoc; + + // __uuidof expressions are always parenthesized. + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "__uuidof")) + return ExprError(); + + ExprResult Result; + + if (isTypeIdInParens()) { + TypeResult Ty = ParseTypeName(); + + // Match the ')'. + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + if (Ty.isInvalid()) + return ExprError(); + + Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true, + Ty.get().getAsOpaquePtr(), RParenLoc); + } else { + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + Result = ParseExpression(); + + // Match the ')'. + if (Result.isInvalid()) + SkipUntil(tok::r_paren); + else { + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false, + Result.release(), RParenLoc); + } + } + + return move(Result); +} + /// \brief Parse a C++ pseudo-destructor expression after the base, /// . or -> operator, and nested-name-specifier have already been /// parsed. diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 17817d4169..60e8c14cf9 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -138,7 +138,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), SuppressAccessChecking(false), NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0), - AnalysisWarnings(*this) + AnalysisWarnings(*this), MSVCGuidDecl(0) { TUScope = 0; if (getLangOptions().CPlusPlus) diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 7857ea9693..c3e2c50312 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -370,6 +370,62 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } +/// \brief Build a Microsoft __uuidof expression with a type operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + Operand, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// \brief Build a Microsoft __uuidof expression with an expression operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *E, + SourceLocation RParenLoc) { + // FIXME: add __uuidof semantic analysis for expr operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + E, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression); +ExprResult +Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // If MSVCGuidDecl has not been cached, do the lookup. + if (!MSVCGuidDecl) { + IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID"); + LookupResult R(*this, GuidII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, Context.getTranslationUnitDecl()); + MSVCGuidDecl = R.getAsSingle<RecordDecl>(); + if (!MSVCGuidDecl) + return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof)); + } + + QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl); + + if (isType) { + // The operand is a type; handle it as such. + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); + if (T.isNull()) + return ExprError(); + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); + + return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc); + } + + // The operand is an expression. + return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); +} + /// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 16114f2ca3..746d6ca04c 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1513,6 +1513,7 @@ public: RParenLoc); } + /// \brief Build a new C++ typeid(expr) expression. /// /// By default, performs semantic analysis to build the new expression. @@ -1525,6 +1526,30 @@ public: RParenLoc); } + /// \brief Build a new C++ __uuidof(type) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + + /// \brief Build a new C++ __uuidof(expr) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + /// \brief Build a new C++ "this" expression. /// /// By default, builds a new "this" expression without performing any @@ -5145,6 +5170,44 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { + if (E->isTypeOperand()) { + TypeSourceInfo *TInfo + = getDerived().TransformType(E->getTypeOperandSourceInfo()); + if (!TInfo) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + TInfo == E->getTypeOperandSourceInfo()) + return SemaRef.Owned(E->Retain()); + + return getDerived().RebuildCXXTypeidExpr(E->getType(), + E->getLocStart(), + TInfo, + E->getLocEnd()); + } + + // We don't know whether the expression is potentially evaluated until + // after we perform semantic analysis, so the expression is potentially + // potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + SubExpr.get() == E->getExprOperand()) + return SemaRef.Owned(E->Retain()); + + return getDerived().RebuildCXXUuidofExpr(E->getType(), + E->getLocStart(), + SubExpr.get(), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { return SemaRef.Owned(E->Retain()); } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 8bfca9431d..93664452d9 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -134,6 +134,7 @@ namespace clang { void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); void VisitCXXTypeidExpr(CXXTypeidExpr *E); + void VisitCXXUuidofExpr(CXXUuidofExpr *E); void VisitCXXThisExpr(CXXThisExpr *E); void VisitCXXThrowExpr(CXXThrowExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); @@ -1028,6 +1029,18 @@ void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) { // typeid(42+2) E->setExprOperand(Reader.ReadSubExpr()); } +void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) { + VisitExpr(E); + E->setSourceRange(Reader.ReadSourceRange(Record, Idx)); + if (E->isTypeOperand()) { // __uuidof(ComType) + E->setTypeOperandSourceInfo( + Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx)); + return; + } + + // __uuidof(expr) + E->setExprOperand(Reader.ReadSubExpr()); +} void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) { VisitExpr(E); @@ -1678,6 +1691,12 @@ Stmt *ASTReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) { case EXPR_CXX_TYPEID_TYPE: S = new (Context) CXXTypeidExpr(Empty, false); break; + case EXPR_CXX_UUIDOF_EXPR: + S = new (Context) CXXUuidofExpr(Empty, true); + break; + case EXPR_CXX_UUIDOF_TYPE: + S = new (Context) CXXUuidofExpr(Empty, false); + break; case EXPR_CXX_THIS: S = new (Context) CXXThisExpr(Empty); break; diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index cda42e1098..403311b8c1 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -131,6 +131,7 @@ namespace clang { void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); void VisitCXXTypeidExpr(CXXTypeidExpr *E); + void VisitCXXUuidofExpr(CXXUuidofExpr *E); void VisitCXXThisExpr(CXXThisExpr *E); void VisitCXXThrowExpr(CXXThrowExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E); @@ -1039,6 +1040,18 @@ void ASTStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) { } } +void ASTStmtWriter::VisitCXXUuidofExpr(CXXUuidofExpr *E) { + VisitExpr(E); + Writer.AddSourceRange(E->getSourceRange(), Record); + if (E->isTypeOperand()) { + Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record); + Code = serialization::EXPR_CXX_UUIDOF_TYPE; + } else { + Writer.AddStmt(E->getExprOperand()); + Code = serialization::EXPR_CXX_UUIDOF_EXPR; + } +} + void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) { VisitExpr(E); Writer.AddSourceLocation(E->getLocation(), Record); |