[cfe-commits] r65622 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/AST/StmtPrinter.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/SemaExpr.cpp test/Sema/offsetof.c

Eli Friedman eli.friedman at gmail.com
Thu Feb 26 22:44:11 PST 2009


Author: efriedma
Date: Fri Feb 27 00:44:11 2009
New Revision: 65622

URL: http://llvm.org/viewvc/llvm-project?rev=65622&view=rev
Log:
Change the AST generated for offsetof a bit so that it looks like a 
normal expression, and change Evaluate and IRGen to evaluate it like a 
normal expression.  This simplifies the code significantly, and fixes 
PR3396.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/offsetof.c

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

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Feb 27 00:44:11 2009
@@ -656,8 +656,6 @@
   }
   static bool classof(const UnaryOperator *) { return true; }
   
-  int64_t evaluateOffsetOf(ASTContext& C) const;
-  
   // Iterators
   virtual child_iterator child_begin();
   virtual child_iterator child_end();

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

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Feb 27 00:44:11 2009
@@ -1331,49 +1331,6 @@
   return getCond()->getIntegerConstantExprValue(C) != 0;
 }
 
-static int64_t evaluateOffsetOf(ASTContext& C, const Expr *E) {
-  if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
-    QualType Ty = ME->getBase()->getType();
-    
-    RecordDecl *RD = Ty->getAsRecordType()->getDecl();
-    const ASTRecordLayout &RL = C.getASTRecordLayout(RD);
-    if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
-      // FIXME: This is linear time. And the fact that we're indexing
-      // into the layout by position in the record means that we're
-      // either stuck numbering the fields in the AST or we have to keep
-      // the linear search (yuck and yuck).
-      unsigned i = 0;
-      for (RecordDecl::field_iterator Field = RD->field_begin(),
-                                   FieldEnd = RD->field_end();
-           Field != FieldEnd; (void)++Field, ++i) {
-        if (*Field == FD)
-          break;
-      }
-      
-      return RL.getFieldOffset(i) + evaluateOffsetOf(C, ME->getBase());
-    }
-  } else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
-    const Expr *Base = ASE->getBase();
-    
-    int64_t size = C.getTypeSize(ASE->getType());
-    size *= ASE->getIdx()->getIntegerConstantExprValue(C).getSExtValue();
-    
-    return size + evaluateOffsetOf(C, Base);
-  } else if (isa<CompoundLiteralExpr>(E))
-    return 0;  
-
-  assert(0 && "Unknown offsetof subexpression!");
-  return 0;
-}
-
-int64_t UnaryOperator::evaluateOffsetOf(ASTContext& C) const
-{
-  assert(Opc == OffsetOf && "Unary operator not offsetof!");
-  
-  unsigned CharSize = C.Target.getCharWidth();
-  return ::evaluateOffsetOf(C, cast<Expr>(Val)) / CharSize;
-}
-
 void SizeOfAlignOfExpr::Destroy(ASTContext& C) {
   // Override default behavior of traversing children. If this has a type
   // operand and the type is a variable-length array, the child iteration

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=65622&r1=65621&r2=65622&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Feb 27 00:44:11 2009
@@ -1064,8 +1064,16 @@
 bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
   // Special case unary operators that do not need their subexpression
   // evaluated.  offsetof/sizeof/alignof are all special.
-  if (E->isOffsetOfOp())
-    return Success(E->evaluateOffsetOf(Info.Ctx), E);
+  if (E->isOffsetOfOp()) {
+    // The AST for offsetof is defined in such a way that we can just
+    // directly Evaluate it as an l-value.
+    APValue LV;
+    if (!EvaluateLValue(E->getSubExpr(), LV, Info))
+      return false;
+    if (LV.getLValueBase())
+      return false;
+    return Success(LV.getLValueOffset(), E);
+  }
 
   if (E->getOpcode() == UnaryOperator::LNot) {
     // LNot's operand isn't necessarily an integer, so we handle it specially.

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=65622&r1=65621&r2=65622&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Feb 27 00:44:11 2009
@@ -724,7 +724,7 @@
 }
 
 bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) {
-  if (isa<CompoundLiteralExpr>(E)) {
+  if (isa<UnaryOperator>(E)) {
     // Base case, print the type and comma.
     OS << E->getType().getAsString() << ", ";
     return true;

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=65622&r1=65621&r2=65622&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Fri Feb 27 00:44:11 2009
@@ -755,47 +755,9 @@
 
 Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E)
 {
-  const Expr* SubExpr = E->getSubExpr();
+  Value* ResultAsPtr = EmitLValue(E->getSubExpr()).getAddress();
   const llvm::Type* ResultType = ConvertType(E->getType());
-  llvm::Value* Result = llvm::Constant::getNullValue(ResultType);
-  while (!isa<CompoundLiteralExpr>(SubExpr)) {
-    if (const MemberExpr *ME = dyn_cast<MemberExpr>(SubExpr)) {
-      SubExpr = ME->getBase();
-      QualType Ty = SubExpr->getType();
-
-      RecordDecl *RD = Ty->getAsRecordType()->getDecl();
-      const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
-      FieldDecl *FD = cast<FieldDecl>(ME->getMemberDecl());
-
-      // FIXME: This is linear time. And the fact that we're indexing
-      // into the layout by position in the record means that we're
-      // either stuck numbering the fields in the AST or we have to keep
-      // the linear search (yuck and yuck).
-      unsigned i = 0;
-      for (RecordDecl::field_iterator Field = RD->field_begin(),
-                                   FieldEnd = RD->field_end();
-           Field != FieldEnd; (void)++Field, ++i) {
-        if (*Field == FD)
-          break;
-      }
-
-      llvm::Value* Offset =
-          llvm::ConstantInt::get(ResultType, RL.getFieldOffset(i) / 8);
-      Result = Builder.CreateAdd(Result, Offset);
-    } else if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SubExpr)) {
-      SubExpr = ASE->getBase();
-      int64_t size = CGF.getContext().getTypeSize(ASE->getType()) / 8;
-      llvm::Value* ElemSize = llvm::ConstantInt::get(ResultType, size);
-      llvm::Value* ElemIndex = CGF.EmitScalarExpr(ASE->getIdx());
-      bool IndexSigned = ASE->getIdx()->getType()->isSignedIntegerType();
-      ElemIndex = Builder.CreateIntCast(ElemIndex, ResultType, IndexSigned);
-      llvm::Value* Offset = Builder.CreateMul(ElemSize, ElemIndex);
-      Result = Builder.CreateAdd(Result, Offset);
-    } else {
-      assert(0 && "This should be impossible!");
-    }
-  }
-  return Result;
+  return Builder.CreatePtrToInt(ResultAsPtr, ResultType, "offsetof");
 }
 
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb 27 00:44:11 2009
@@ -4270,16 +4270,17 @@
   if (!Dependent && !ArgTy->isRecordType())
     return Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy;
 
-  // Otherwise, create a compound literal expression as the base, and
-  // iteratively process the offsetof designators.
-  InitListExpr *IList =
-      new (Context) InitListExpr(SourceLocation(), 0, 0, SourceLocation());
-  IList->setType(ArgTy);
-  Expr *Res =
-      new (Context) CompoundLiteralExpr(SourceLocation(), ArgTy, IList, false);
+  // Otherwise, create a null pointer as the base, and iteratively process
+  // the offsetof designators.
+  QualType ArgTyPtr = Context.getPointerType(ArgTy);
+  Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
+  Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref, 
+                                    ArgTy, SourceLocation());
 
   // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
   // GCC extension, diagnose them.
+  // FIXME: This diagnostic isn't actually visible because the location is in
+  // a system header!
   if (NumComponents != 1)
     Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
       << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
@@ -4300,6 +4301,10 @@
 
         // FIXME: C++: Verify that operator[] isn't overloaded.
 
+        // Promote the array so it looks more like a normal array subscript
+        // expression.
+        DefaultFunctionArrayConversion(Res);
+
         // C99 6.5.2.1p1
         Expr *Idx = static_cast<Expr*>(OC.U.E);
         if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())

Modified: cfe/trunk/test/Sema/offsetof.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/offsetof.c?rev=65622&r1=65621&r2=65622&view=diff

==============================================================================
--- cfe/trunk/test/Sema/offsetof.c (original)
+++ cfe/trunk/test/Sema/offsetof.c Fri Feb 27 00:44:11 2009
@@ -35,3 +35,13 @@
 
 struct s3 { int a; }; 
 int v3 = __builtin_offsetof(struct s3, a) == 0 ? 0 : f();
+
+// PR3396
+struct sockaddr_un {
+ unsigned char sun_len;
+ char sun_path[104];
+};
+int a(int len) {
+int a[__builtin_offsetof(struct sockaddr_un, sun_path[len+1])];
+}
+





More information about the cfe-commits mailing list