[cfe-commits] [PATCH][MS] - operator __uuidof implementation part 1

Douglas Gregor dgregor at apple.com
Fri Sep 3 08:56:32 PDT 2010


On Sep 1, 2010, at 8:49 PM, Francois Pichet wrote:

> Hi,
> 
> This patch is part 1 of X of my implementation of the Microsoft
> __uuidof operator.
> I want to go incrementally for this one because I don't want to submit
> a huge patch.
> The basic parsing is completed but some sema and all the code gen are missing.
> 
> __uuidof is similar to the typeid operator so I used that operator as
> template of what to do.

Index: include/clang/AST/ExprCXX.h
===================================================================
--- include/clang/AST/ExprCXX.h	(revision 112800)
+++ include/clang/AST/ExprCXX.h	(working copy)
@@ -396,6 +396,82 @@
   virtual child_iterator child_end();
 };
 
+/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets
+/// the _GUID that corresponds to the supplied type or expression.
+///
+/// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr)
+class CXXUuidofExpr : public Expr {

Is __uuidof only available in C++ mode, or does MSVC also allow it in C mode?

+private:
+  llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
+  SourceRange Range;
+
+public:
+  CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
+    : Expr(CXXUuidofExprClass, Ty, 
+        // FIXME: is __uuidof really never type-dependent?
+        false,
+        // FIXME: is __uuidof really value-dependent if the type or 
+        // expression are dependent?
+        Operand->getType()->isDependentType()),
+      Operand(Operand), Range(R) { }
+  
+  CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
+    : Expr(CXXUuidofExprClass, Ty,
+        // FIXME: is __uuidof really never type-dependent?
+        false,
+        // FIXME: is __uuidof really value-dependent if the type or
+        // expression are dependent?
+        Operand->isTypeDependent() || Operand->isValueDependent()),
+      Operand(Operand), Range(R) { }

Yes, it makes sense that __uuidof is never type-dependent and is only value-dependent if the argument is type- or value-dependent.

Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 112800)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -534,6 +534,55 @@
   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 ')'.
+    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::PotentiallyPotentiallyEvaluated);

Is there anything dynamci about __uuidof? In other words, is the result of __uuidof always a constant, or can it involve run-time computation? If it does not involve run-time computation, then you can use the Unevaluated context rather than the PotentiallyPotentiallyEvaluated context.

+/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression);
+ExprResult
+Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+                     bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
+
+  // Check that _GUID is defined.
+  IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("_GUID");
+  LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
+  LookupQualifiedName(R, Context.getTranslationUnitDecl());
+  RecordDecl *TypeInfoRecordDecl = R.getAsSingle<RecordDecl>();
+  if (!TypeInfoRecordDecl)
+    return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof));
+  
+  QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);

You shouldn't do this lookup every time. Instead, you should perform the lookup for _GUID lazily and cache the result in Sema.

@@ -5165,6 +5190,45 @@
 
 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::PotentiallyPotentiallyEvaluated);

Same comment as before about Unevaluated vs. PotentiallyPotentiallyEvaluated.

Otherwise, things are looking good!  Don't forget to add AST reading/writing support for this new expression kind.

	- Doug





More information about the cfe-commits mailing list