[cfe-commits] r41613 - in /cfe/trunk: AST/Expr.cpp Sema/Sema.h Sema/SemaExpr.cpp include/clang/AST/Expr.h include/clang/AST/StmtVisitor.h include/clang/Basic/DiagnosticKinds.def

Chris Lattner sabre at nondot.org
Thu Aug 30 10:45:32 PDT 2007


Author: lattner
Date: Thu Aug 30 12:45:32 2007
New Revision: 41613

URL: http://llvm.org/viewvc/llvm-project?rev=41613&view=rev
Log:
implement initial sema support for __builtin_offsetof

Modified:
    cfe/trunk/AST/Expr.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/StmtVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Expr.cpp?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/AST/Expr.cpp (original)
+++ cfe/trunk/AST/Expr.cpp Thu Aug 30 12:45:32 2007
@@ -69,6 +69,7 @@
   case SizeOf:  return "sizeof";
   case AlignOf: return "alignof";
   case Extension: return "__extension__";
+  case OffsetOf: return "__builtin_offsetof";
   }
 }
 

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Aug 30 12:45:32 2007
@@ -306,7 +306,14 @@
   
   virtual ExprResult ParseStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt,
                                    SourceLocation RPLoc); // "({..})"
-                                   
+
+  /// __builtin_offsetof(type, a.b[123][456].c)
+  virtual ExprResult ParseBuiltinOffsetOf(SourceLocation BuiltinLoc,
+                                          SourceLocation TypeLoc, TypeTy *Arg1,
+                                          OffsetOfComponent *CompPtr,
+                                          unsigned NumComponents,
+                                          SourceLocation RParenLoc);
+    
   // __builtin_types_compatible_p(type1, type2)
   virtual ExprResult ParseTypesCompatibleExpr(SourceLocation BuiltinLoc, 
                                               TypeTy *arg1, TypeTy *arg2,

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Thu Aug 30 12:45:32 2007
@@ -334,7 +334,7 @@
   QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
 
   // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
-  // to the expression *((e1)+(e2)). This means the array "Base" may actually be 
+  // to the expression *((e1)+(e2)). This means the array "Base" may actually be
   // in the subscript position. As a result, we need to derive the array base 
   // and index from the expression types.
   Expr *BaseExpr, *IndexExpr;
@@ -619,7 +619,8 @@
   if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
     if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
       if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
-        if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args, NumArgsInCall))
+        if (CheckFunctionCall(Fn, LParenLoc, RParenLoc, FDecl, Args,
+                              NumArgsInCall))
           return true;
 
   return new CallExpr(Fn, Args, NumArgsInCall, resultType, RParenLoc);
@@ -693,7 +694,7 @@
   if (const RecordType *LHSRT = lexT->getAsRecordType()) {    // C99 6.5.15p3
     if (const RecordType *RHSRT = rexT->getAsRecordType()) {
       
-      if (LHSRT->getDecl()->getIdentifier() ==RHSRT->getDecl()->getIdentifier()) 
+      if (LHSRT->getDecl()->getIdentifier() ==RHSRT->getDecl()->getIdentifier())
         return lexT;
       
       Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands,
@@ -730,9 +731,10 @@
         return lexT; // FIXME: this is an _ext - is this return o.k?
       }
       // The pointer types are compatible.
-      // C99 6.5.15p6: If both operands are pointers to compatible types *or* to 
-      // differently qualified versions of compatible types, the result type is a 
-      // pointer to an appropriately qualified version of the *composite* type.
+      // C99 6.5.15p6: If both operands are pointers to compatible types *or* to
+      // differently qualified versions of compatible types, the result type is
+      // a pointer to an appropriately qualified version of the *composite*
+      // type.
       return lexT; // FIXME: Need to return the composite type.
     }
   }
@@ -818,7 +820,7 @@
     DefaultFunctionArrayConversion(expr);
 }
 
-/// UsualArithmeticConversions - Performs various conversions that are common to 
+/// UsualArithmeticConversions - Performs various conversions that are common to
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
 /// routine returns the first non-arithmetic type found. The client is 
 /// responsible for emitting appropriate error diagnostics.
@@ -1315,7 +1317,8 @@
   // it is the unqualified version of the type of the left operand. 
   // C99 6.5.16.1p2: In simple assignment, the value of the right operand
   // is converted to the type of the assignment expression (above).
-  // C++ 5.17p1: the type of the assignment expression is that of its left oprdu.
+  // C++ 5.17p1: the type of the assignment expression is that of its left
+  // oprdu.
   return hadError ? QualType() : lhsType.getUnqualifiedType();
 }
 
@@ -1715,6 +1718,68 @@
   return new StmtExpr(Compound, Ty, LPLoc, RPLoc);
 }
 
+Sema::ExprResult Sema::ParseBuiltinOffsetOf(SourceLocation BuiltinLoc,
+                                            SourceLocation TypeLoc,
+                                            TypeTy *argty,
+                                            OffsetOfComponent *CompPtr,
+                                            unsigned NumComponents,
+                                            SourceLocation RPLoc) {
+  QualType ArgTy = QualType::getFromOpaquePtr(argty);
+  assert(!ArgTy.isNull() && "Missing type argument!");
+  
+  // We must have at least one component that refers to the type, and the first
+  // one is known to be a field designator.  Verify that the ArgTy represents
+  // a struct/union/class.
+  if (!ArgTy->isRecordType())
+    return Diag(TypeLoc, diag::err_offsetof_record_type,ArgTy.getAsString());
+  
+  // Otherwise, create a compound literal expression as the base, and
+  // iteratively process the offsetof designators.
+  Expr *Res = new CompoundLiteralExpr(ArgTy, 0);
+  
+  for (unsigned i = 0; i != NumComponents; ++i) {
+    const OffsetOfComponent &OC = CompPtr[i];
+    if (OC.isBrackets) {
+      // Offset of an array sub-field.  TODO: Should we allow vector elements?
+      const ArrayType *AT = Res->getType()->getAsArrayType();
+      if (!AT) {
+        delete Res;
+        return Diag(OC.LocEnd, diag::err_offsetof_array_type,
+                    Res->getType().getAsString());
+      }
+      
+      // C99 6.5.2.1p1
+      Expr *Idx = static_cast<Expr*>(OC.U.E);
+      if (!Idx->getType()->isIntegerType())
+        return Diag(Idx->getLocStart(), diag::err_typecheck_subscript,
+                    Idx->getSourceRange());
+      
+      Res = new ArraySubscriptExpr(Res, Idx, AT->getElementType(), OC.LocEnd);
+      continue;
+    }
+    
+    const RecordType *RC = Res->getType()->getAsRecordType();
+    if (!RC) {
+      delete Res;
+      return Diag(OC.LocEnd, diag::err_offsetof_record_type,
+                  Res->getType().getAsString());
+    }
+      
+    // Get the decl corresponding to this.
+    RecordDecl *RD = RC->getDecl();
+    FieldDecl *MemberDecl = RD->getMember(OC.U.IdentInfo);
+    if (!MemberDecl)
+      return Diag(BuiltinLoc, diag::err_typecheck_no_member,
+                  OC.U.IdentInfo->getName(),
+                  SourceRange(OC.LocStart, OC.LocEnd));
+    Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd);
+  }
+  
+  return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
+                           BuiltinLoc);
+}
+
+
 Sema::ExprResult Sema::ParseTypesCompatibleExpr(SourceLocation BuiltinLoc, 
                                                 TypeTy *arg1, TypeTy *arg2,
                                                 SourceLocation RPLoc) {
@@ -1723,7 +1788,7 @@
   
   assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
   
-  return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2, RPLoc);
+  return new TypesCompatibleExpr(Context.IntTy, BuiltinLoc, argT1, argT2,RPLoc);
 }
 
 Sema::ExprResult Sema::ParseChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond, 

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Aug 30 12:45:32 2007
@@ -32,7 +32,6 @@
   QualType TR;
 protected:
   Expr(StmtClass SC, QualType T) : Stmt(SC), TR(T) {}
-  ~Expr() {}
 public:  
   QualType getType() const { return TR; }
   void setType(QualType t) { TR = t; }
@@ -329,6 +328,10 @@
 ///   applied to a non-complex value, the former returns its operand and the
 ///   later returns zero in the type of the operand.
 ///
+/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
+///   subexpression is a compound literal with the various MemberExpr and 
+///   ArraySubscriptExpr's applied to it.
+///
 class UnaryOperator : public Expr {
 public:
   // Note that additions to this should also update the StmtVisitor class.
@@ -340,7 +343,8 @@
     Not, LNot,        // [C99 6.5.3.3] Unary arithmetic operators.
     SizeOf, AlignOf,  // [C99 6.5.3.4] Sizeof (expr, not type) operator.
     Real, Imag,       // "__real expr"/"__imag expr" Extension.
-    Extension         // __extension__ marker.
+    Extension,        // __extension__ marker.
+    OffsetOf          // __builtin_offsetof
   };
 private:
   Expr *Val;
@@ -431,12 +435,11 @@
   SourceLocation RBracketLoc;
 public:
   ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t,
-                     SourceLocation rbracketloc) : 
-    Expr(ArraySubscriptExprClass, t),
-    RBracketLoc(rbracketloc) {
-      SubExprs[LHS] = lhs;
-      SubExprs[RHS] = rhs;
-    }
+                     SourceLocation rbracketloc)
+  : Expr(ArraySubscriptExprClass, t), RBracketLoc(rbracketloc) {
+    SubExprs[LHS] = lhs;
+    SubExprs[RHS] = rhs;
+  }
   
   /// An array access can be written A[4] or 4[A] (both are equivalent).
   /// - getBase() and getIdx() always present the normalized view: A[4].
@@ -636,7 +639,11 @@
   const Expr *getInitializer() const { return Init; }
   Expr *getInitializer() { return Init; }
   
-  virtual SourceRange getSourceRange() const { return Init->getSourceRange(); }
+  virtual SourceRange getSourceRange() const {
+    if (Init)
+      return Init->getSourceRange();
+    return SourceRange();
+  }
 
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == CompoundLiteralExprClass; 
@@ -908,7 +915,7 @@
   QualType getArgType1() const { return Type1; }
   QualType getArgType2() const { return Type2; }
   
-  int typesAreCompatible() const { return Type::typesAreCompatible(Type1,Type2); }
+  int typesAreCompatible() const {return Type::typesAreCompatible(Type1,Type2);}
   
   virtual SourceRange getSourceRange() const {
     return SourceRange(BuiltinLoc, RParenLoc);

Modified: cfe/trunk/include/clang/AST/StmtVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtVisitor.h?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtVisitor.h (original)
+++ cfe/trunk/include/clang/AST/StmtVisitor.h Thu Aug 30 12:45:32 2007
@@ -95,6 +95,7 @@
       case UnaryOperator::Real:         DISPATCH(UnaryReal,      UnaryOperator);
       case UnaryOperator::Imag:         DISPATCH(UnaryImag,      UnaryOperator);
       case UnaryOperator::Extension:    DISPATCH(UnaryExtension, UnaryOperator);
+      case UnaryOperator::OffsetOf:     DISPATCH(UnaryExtension, UnaryOperator);
       }          
     }
     
@@ -158,7 +159,7 @@
   UNARYOP_FALLBACK(Not)       UNARYOP_FALLBACK(LNot)
   UNARYOP_FALLBACK(SizeOf)    UNARYOP_FALLBACK(AlignOf)
   UNARYOP_FALLBACK(Real)      UNARYOP_FALLBACK(Imag)
-  UNARYOP_FALLBACK(Extension)
+  UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
 #undef UNARYOP_FALLBACK
   
   // Base case, ignore it. :)

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41613&r1=41612&r2=41613&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Aug 30 12:45:32 2007
@@ -581,6 +581,11 @@
      "invalid application of 'sizeof' to an incomplete type '%0'")
 DIAG(err_alignof_incomplete_type, ERROR,
      "invalid application of '__alignof' to an incomplete type '%0'")
+DIAG(err_offsetof_record_type, ERROR,
+     "offsetof requires struct, union, or class type, '%0' invalid")
+DIAG(err_offsetof_array_type, ERROR,
+     "offsetof requires array type, '%0' invalid")
+     
 DIAG(err_invalid_suffix_integer_constant, ERROR,
      "invalid suffix '%0' on integer constant")
 DIAG(err_invalid_suffix_float_constant, ERROR,





More information about the cfe-commits mailing list