[cfe-commits] r94826 - in /cfe/trunk: lib/AST/Expr.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h test/CodeGenCXX/reference-init.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 29 11:14:03 PST 2010
Author: dgregor
Date: Fri Jan 29 13:14:02 2010
New Revision: 94826
URL: http://llvm.org/viewvc/llvm-project?rev=94826&view=rev
Log:
Fix reference binding of const lvalue references to bit-fields, which
requires a temporary. Previously, we were building an initialization
sequence that bound to the bit-field as if it were a real lvalue. Note
that we previously (and still) diagnose binding of non-const
references to bit-fields, as we should.
There's no real way to test that this code is correct, since reference
binding does not *currently* have any representation in the AST. This
fix should make it easier for that to happen, so I've verified this
fix with...
Added InitializationSequence::dump(), to print an initialization
sequence for debugging purposes.
Modified:
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
cfe/trunk/test/CodeGenCXX/reference-init.cpp
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=94826&r1=94825&r2=94826&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Jan 29 13:14:02 2010
@@ -1958,6 +1958,13 @@
FieldDecl *Expr::getBitField() {
Expr *E = this->IgnoreParens();
+ while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ E = ICE->getSubExpr()->IgnoreParens();
+ else
+ break;
+ }
+
if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
if (Field->isBitField())
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=94826&r1=94825&r2=94826&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Jan 29 13:14:02 2010
@@ -2327,16 +2327,20 @@
// - is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
//
- // Per C++ [over.best.ics]p2, we ignore whether the lvalue is a
+ // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
// bit-field when we're determining whether the reference initialization
- // can occur. This property will be checked by PerformInitialization.
+ // can occur. However, we do pay attention to whether it is a bit-field
+ // to decide whether we're actually binding to a temporary created from
+ // the bit-field.
if (DerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1, T2Quals),
/*isLValue=*/true);
if (T1Quals != T2Quals)
Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
+ bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+ Initializer->getBitField();
+ Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
return;
}
@@ -3665,6 +3669,194 @@
return true;
}
+void InitializationSequence::dump(llvm::raw_ostream &OS) const {
+ switch (SequenceKind) {
+ case FailedSequence: {
+ OS << "Failed sequence: ";
+ switch (Failure) {
+ case FK_TooManyInitsForReference:
+ OS << "too many initializers for reference";
+ break;
+
+ case FK_ArrayNeedsInitList:
+ OS << "array requires initializer list";
+ break;
+
+ case FK_ArrayNeedsInitListOrStringLiteral:
+ OS << "array requires initializer list or string literal";
+ break;
+
+ case FK_AddressOfOverloadFailed:
+ OS << "address of overloaded function failed";
+ break;
+
+ case FK_ReferenceInitOverloadFailed:
+ OS << "overload resolution for reference initialization failed";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToTemporary:
+ OS << "non-const lvalue reference bound to temporary";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToUnrelated:
+ OS << "non-const lvalue reference bound to unrelated type";
+ break;
+
+ case FK_RValueReferenceBindingToLValue:
+ OS << "rvalue reference bound to an lvalue";
+ break;
+
+ case FK_ReferenceInitDropsQualifiers:
+ OS << "reference initialization drops qualifiers";
+ break;
+
+ case FK_ReferenceInitFailed:
+ OS << "reference initialization failed";
+ break;
+
+ case FK_ConversionFailed:
+ OS << "conversion failed";
+ break;
+
+ case FK_TooManyInitsForScalar:
+ OS << "too many initializers for scalar";
+ break;
+
+ case FK_ReferenceBindingToInitList:
+ OS << "referencing binding to initializer list";
+ break;
+
+ case FK_InitListBadDestinationType:
+ OS << "initializer list for non-aggregate, non-scalar type";
+ break;
+
+ case FK_UserConversionOverloadFailed:
+ OS << "overloading failed for user-defined conversion";
+ break;
+
+ case FK_ConstructorOverloadFailed:
+ OS << "constructor overloading failed";
+ break;
+
+ case FK_DefaultInitOfConst:
+ OS << "default initialization of a const variable";
+ break;
+ }
+ OS << '\n';
+ return;
+ }
+
+ case DependentSequence:
+ OS << "Dependent sequence: ";
+ return;
+
+ case UserDefinedConversion:
+ OS << "User-defined conversion sequence: ";
+ break;
+
+ case ConstructorInitialization:
+ OS << "Constructor initialization sequence: ";
+ break;
+
+ case ReferenceBinding:
+ OS << "Reference binding: ";
+ break;
+
+ case ListInitialization:
+ OS << "List initialization: ";
+ break;
+
+ case ZeroInitialization:
+ OS << "Zero initialization\n";
+ return;
+
+ case NoInitialization:
+ OS << "No initialization\n";
+ return;
+
+ case StandardConversion:
+ OS << "Standard conversion: ";
+ break;
+
+ case CAssignment:
+ OS << "C assignment: ";
+ break;
+
+ case StringInit:
+ OS << "String initialization: ";
+ break;
+ }
+
+ for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
+ if (S != step_begin()) {
+ OS << " -> ";
+ }
+
+ switch (S->Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ OS << "resolve address of overloaded function";
+ break;
+
+ case SK_CastDerivedToBaseRValue:
+ OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_CastDerivedToBaseLValue:
+ OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+ break;
+
+ case SK_BindReference:
+ OS << "bind reference to lvalue";
+ break;
+
+ case SK_BindReferenceToTemporary:
+ OS << "bind reference to a temporary";
+ break;
+
+ case SK_UserConversion:
+ OS << "user-defined conversion via " << S->Function->getNameAsString();
+ break;
+
+ case SK_QualificationConversionRValue:
+ OS << "qualification conversion (rvalue)";
+
+ case SK_QualificationConversionLValue:
+ OS << "qualification conversion (lvalue)";
+ break;
+
+ case SK_ConversionSequence:
+ OS << "implicit conversion sequence (";
+ S->ICS->DebugPrint(); // FIXME: use OS
+ OS << ")";
+ break;
+
+ case SK_ListInitialization:
+ OS << "list initialization";
+ break;
+
+ case SK_ConstructorInitialization:
+ OS << "constructor initialization";
+ break;
+
+ case SK_ZeroInitialization:
+ OS << "zero initialization";
+ break;
+
+ case SK_CAssignment:
+ OS << "C assignment";
+ break;
+
+ case SK_StringInit:
+ OS << "string initialization";
+ break;
+ }
+ }
+}
+
+void InitializationSequence::dump() const {
+ dump(llvm::errs());
+}
+
//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=94826&r1=94825&r2=94826&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Fri Jan 29 13:14:02 2010
@@ -21,6 +21,10 @@
#include "llvm/ADT/SmallVector.h"
#include <cassert>
+namespace llvm {
+ class raw_ostream;
+}
+
namespace clang {
class CXXBaseSpecifier;
@@ -658,6 +662,14 @@
assert(getKind() == FailedSequence && "Not an initialization failure!");
return Failure;
}
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(llvm::raw_ostream &OS) const;
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// standard error, for debugging purposes.
+ void dump() const;
};
} // end namespace clang
Modified: cfe/trunk/test/CodeGenCXX/reference-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/reference-init.cpp?rev=94826&r1=94825&r2=94826&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/reference-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/reference-init.cpp Fri Jan 29 13:14:02 2010
@@ -19,3 +19,6 @@
struct Foo { int foo; };
Foo& ignoreSetMutex = *(new Foo);
+// Binding to a bit-field that requires a temporary.
+struct { int bitfield : 3; } s = { 3 };
+const int &s2 = s.bitfield;
More information about the cfe-commits
mailing list