r242608 - [AST] Cleanup ExprIterator.

Yaron Keren yaron.keren at gmail.com
Sat Jul 18 13:15:19 PDT 2015


Hi,

The Visual C++ library in debug mode complains that "vector iterator not
dereferencable" about

+  CGF.EmitCallArgs(Args, FPT, &*ArgVec.begin(), &*ArgVec.end(), CD,
+                   IsCopy ? 1 : 0);

when running  Clang :: CodeGenCXX/dllexport.cpp & Clang ::
CodeGenCXX/microsoft-abi-throw.cpp tests.

Dereferencing ArgVec.end() is undefined behaviour and so is
dereferencing ArgVec.begin()
when the ArgVec is empty.

Modifying the call to

  CGF.EmitCallArgs(Args, FPT, ArgVec.data(), ArgVec.data() + ArgVec.size(),
CD,
                   IsCopy ? 1 : 0);

thus avoiding the dereference passes the tests.

Yaron




2015-07-18 17:35 GMT+03:00 Benjamin Kramer <benny.kra at googlemail.com>:

> Author: d0k
> Date: Sat Jul 18 09:35:53 2015
> New Revision: 242608
>
> URL: http://llvm.org/viewvc/llvm-project?rev=242608&view=rev
> Log:
> [AST] Cleanup ExprIterator.
>
> - Make it a proper random access iterator with a little help from
> iterator_adaptor_base
> - Clean up users of magic dereferencing. The iterator should behave like
> an Expr **.
> - Make it an implementation detail of Stmt. This allows inlining of the
> assertions.
>
> Modified:
>     cfe/trunk/include/clang/AST/Stmt.h
>     cfe/trunk/lib/AST/Expr.cpp
>     cfe/trunk/lib/AST/StmtPrinter.cpp
>     cfe/trunk/lib/CodeGen/CGCall.cpp
>     cfe/trunk/lib/CodeGen/CGClass.cpp
>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.h
>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>
> Modified: cfe/trunk/include/clang/AST/Stmt.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Stmt.h (original)
> +++ cfe/trunk/include/clang/AST/Stmt.h Sat Jul 18 09:35:53 2015
> @@ -22,6 +22,7 @@
>  #include "clang/Basic/SourceLocation.h"
>  #include "llvm/ADT/ArrayRef.h"
>  #include "llvm/ADT/PointerIntPair.h"
> +#include "llvm/ADT/iterator.h"
>  #include "llvm/Support/Compiler.h"
>  #include "llvm/Support/ErrorHandling.h"
>  #include <string>
> @@ -49,57 +50,6 @@ namespace clang {
>    class Token;
>    class VarDecl;
>
> -
> //===--------------------------------------------------------------------===//
> -  // ExprIterator - Iterators for iterating over Stmt* arrays that contain
> -  //  only Expr*.  This is needed because AST nodes use Stmt* arrays to
> store
> -  //  references to children (to be compatible with StmtIterator).
> -
> //===--------------------------------------------------------------------===//
> -
> -  class Stmt;
> -  class Expr;
> -
> -  class ExprIterator : public std::iterator<std::forward_iterator_tag,
> -                                            Expr *&, ptrdiff_t,
> -                                            Expr *&, Expr *&> {
> -    Stmt** I;
> -  public:
> -    ExprIterator(Stmt** i) : I(i) {}
> -    ExprIterator() : I(nullptr) {}
> -    ExprIterator& operator++() { ++I; return *this; }
> -    ExprIterator operator-(size_t i) { return I-i; }
> -    ExprIterator operator+(size_t i) { return I+i; }
> -    Expr* operator[](size_t idx);
> -    // FIXME: Verify that this will correctly return a signed distance.
> -    signed operator-(const ExprIterator& R) const { return I - R.I; }
> -    Expr* operator*() const;
> -    Expr* operator->() const;
> -    bool operator==(const ExprIterator& R) const { return I == R.I; }
> -    bool operator!=(const ExprIterator& R) const { return I != R.I; }
> -    bool operator>(const ExprIterator& R) const { return I > R.I; }
> -    bool operator>=(const ExprIterator& R) const { return I >= R.I; }
> -  };
> -
> -  class ConstExprIterator : public
> std::iterator<std::forward_iterator_tag,
> -                                                 const Expr *&, ptrdiff_t,
> -                                                 const Expr *&,
> -                                                 const Expr *&> {
> -    const Stmt * const *I;
> -  public:
> -    ConstExprIterator(const Stmt * const *i) : I(i) {}
> -    ConstExprIterator() : I(nullptr) {}
> -    ConstExprIterator& operator++() { ++I; return *this; }
> -    ConstExprIterator operator+(size_t i) const { return I+i; }
> -    ConstExprIterator operator-(size_t i) const { return I-i; }
> -    const Expr * operator[](size_t idx) const;
> -    signed operator-(const ConstExprIterator& R) const { return I - R.I; }
> -    const Expr * operator*() const;
> -    const Expr * operator->() const;
> -    bool operator==(const ConstExprIterator& R) const { return I == R.I; }
> -    bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
> -    bool operator>(const ConstExprIterator& R) const { return I > R.I; }
> -    bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
> -  };
> -
>
>  //===----------------------------------------------------------------------===//
>  // AST classes for statements.
>
>  //===----------------------------------------------------------------------===//
> @@ -337,6 +287,39 @@ public:
>    /// de-serialization).
>    struct EmptyShell { };
>
> +protected:
> +  /// Iterator for iterating over Stmt * arrays that contain only Expr *
> +  ///
> +  /// This is needed because AST nodes use Stmt* arrays to store
> +  /// references to children (to be compatible with StmtIterator).
> +  struct ExprIterator
> +      : llvm::iterator_adaptor_base<ExprIterator, Stmt **,
> +                                    std::random_access_iterator_tag, Expr
> *> {
> +    ExprIterator() : iterator_adaptor_base(nullptr) {}
> +    ExprIterator(Stmt **I) : iterator_adaptor_base(I) {}
> +
> +    reference operator*() const {
> +      assert((*I)->getStmtClass() >= firstExprConstant &&
> +             (*I)->getStmtClass() <= lastExprConstant);
> +      return *reinterpret_cast<Expr **>(I);
> +    }
> +  };
> +
> +  /// Const iterator for iterating over Stmt * arrays that contain only
> Expr *
> +  struct ConstExprIterator
> +      : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const
> *,
> +                                    std::random_access_iterator_tag,
> +                                    const Expr *const> {
> +    ConstExprIterator() : iterator_adaptor_base(nullptr) {}
> +    ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {}
> +
> +    reference operator*() const {
> +      assert((*I)->getStmtClass() >= firstExprConstant &&
> +             (*I)->getStmtClass() <= lastExprConstant);
> +      return *reinterpret_cast<const Expr *const *>(I);
> +    }
> +  };
> +
>  private:
>    /// \brief Whether statistic collection is enabled.
>    static bool StatisticsEnabled;
>
> Modified: cfe/trunk/lib/AST/Expr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Expr.cpp (original)
> +++ cfe/trunk/lib/AST/Expr.cpp Sat Jul 18 09:35:53 2015
> @@ -4163,19 +4163,6 @@ PseudoObjectExpr::PseudoObjectExpr(QualT
>  }
>
>
>  //===----------------------------------------------------------------------===//
> -//  ExprIterator.
>
> -//===----------------------------------------------------------------------===//
> -
> -Expr* ExprIterator::operator[](size_t idx) { return cast<Expr>(I[idx]); }
> -Expr* ExprIterator::operator*() const { return cast<Expr>(*I); }
> -Expr* ExprIterator::operator->() const { return cast<Expr>(*I); }
> -const Expr* ConstExprIterator::operator[](size_t idx) const {
> -  return cast<Expr>(I[idx]);
> -}
> -const Expr* ConstExprIterator::operator*() const { return cast<Expr>(*I);
> }
> -const Expr* ConstExprIterator::operator->() const { return
> cast<Expr>(*I); }
> -
>
> -//===----------------------------------------------------------------------===//
>  //  Child Iterators for iterating over subexpressions/substatements
>
>  //===----------------------------------------------------------------------===//
>
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Sat Jul 18 09:35:53 2015
> @@ -1768,7 +1768,7 @@ void StmtPrinter::VisitCXXTemporaryObjec
>    for (CXXTemporaryObjectExpr::arg_iterator Arg = Node->arg_begin(),
>                                           ArgEnd = Node->arg_end();
>         Arg != ArgEnd; ++Arg) {
> -    if (Arg->isDefaultArgument())
> +    if ((*Arg)->isDefaultArgument())
>        break;
>      if (Arg != Node->arg_begin())
>        OS << ", ";
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Sat Jul 18 09:35:53 2015
> @@ -2829,7 +2829,7 @@ void CodeGenFunction::EmitCallArgs(CallA
>      for (int I = ArgTypes.size() - 1; I >= 0; --I) {
>        CallExpr::const_arg_iterator Arg = ArgBeg + I;
>        EmitCallArg(Args, *Arg, ArgTypes[I]);
> -      EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
> +      EmitNonNullArgCheck(Args.back().RV, ArgTypes[I],
> (*Arg)->getExprLoc(),
>                            CalleeDecl, ParamsToSkip + I);
>      }
>
> @@ -2843,7 +2843,7 @@ void CodeGenFunction::EmitCallArgs(CallA
>      CallExpr::const_arg_iterator Arg = ArgBeg + I;
>      assert(Arg != ArgEnd);
>      EmitCallArg(Args, *Arg, ArgTypes[I]);
> -    EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], Arg->getExprLoc(),
> +    EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
>                          CalleeDecl, ParamsToSkip + I);
>    }
>  }
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Sat Jul 18 09:35:53 2015
> @@ -1832,7 +1832,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyC
>             "trivial 1-arg ctor not a copy/move ctor");
>      EmitAggregateCopyCtor(This, Src,
>                            getContext().getTypeDeclType(D->getParent()),
> -                          E->arg_begin()->getType());
> +                          (*E->arg_begin())->getType());
>      return;
>    }
>    llvm::Value *Callee = CGM.getAddrOfCXXStructor(D,
> StructorType::Complete);
>
> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sat Jul 18 09:35:53 2015
> @@ -196,7 +196,7 @@ RValue CodeGenFunction::EmitCXXMemberOrO
>          // Trivial move and copy ctor are the same.
>          assert(CE->getNumArgs() == 1 && "unexpected argcount for trivial
> ctor");
>          llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
> -        EmitAggregateCopy(This, RHS, CE->arg_begin()->getType());
> +        EmitAggregateCopy(This, RHS, (*CE->arg_begin())->getType());
>          return RValue::get(This);
>        }
>        llvm_unreachable("unknown trivial member function");
> @@ -1089,8 +1089,7 @@ RValue CodeGenFunction::EmitBuiltinNewDe
>                                                   bool IsDelete) {
>    CallArgList Args;
>    const Stmt *ArgS = Arg;
> -  EmitCallArgs(Args, *Type->param_type_begin(),
> -               ConstExprIterator(&ArgS), ConstExprIterator(&ArgS + 1));
> +  EmitCallArgs(Args, *Type->param_type_begin(), &ArgS, &ArgS + 1);
>    // Find the allocation or deallocation function that we're calling.
>    ASTContext &Ctx = getContext();
>    DeclarationName Name = Ctx.DeclarationNames
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Jul 18 09:35:53 2015
> @@ -2992,7 +2992,7 @@ public:
>                           .getCanonicalType((*I).getNonReferenceType())
>                           .getTypePtr() ==
>                       getContext()
> -                         .getCanonicalType(Arg->getType())
> +                         .getCanonicalType((*Arg)->getType())
>                           .getTypePtr())) &&
>                 "type mismatch in call argument!");
>          ArgTypes.push_back(*I);
>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=242608&r1=242607&r2=242608&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Sat Jul 18 09:35:53 2015
> @@ -3803,9 +3803,8 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure
>    CodeGenFunction::RunCleanupsScope Cleanups(CGF);
>
>    const auto *FPT = CD->getType()->castAs<FunctionProtoType>();
> -  ConstExprIterator ArgBegin(ArgVec.data()),
> -      ArgEnd(ArgVec.data() + ArgVec.size());
> -  CGF.EmitCallArgs(Args, FPT, ArgBegin, ArgEnd, CD, IsCopy ? 1 : 0);
> +  CGF.EmitCallArgs(Args, FPT, &*ArgVec.begin(), &*ArgVec.end(), CD,
> +                   IsCopy ? 1 : 0);
>
>    // Insert any ABI-specific implicit constructor arguments.
>    unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150718/ea1dcd18/attachment.html>


More information about the cfe-commits mailing list