Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -8031,6 +8031,15 @@ /// Potentially visit a MemberExpr's base expression. void VisitIgnoredBaseExpression(const Expr *E) { + // If E is a reference, and if so, there is no side effect. + if (const DeclRefExpr *DRE = + dyn_cast(E->IgnoreParenImpCasts())) { + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { + if (VD->getType()->isReferenceType()) { + return; + } + } + } // While MSVC doesn't evaluate the base expression, it does diagnose the // presence of side-effecting behavior. if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx)) Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2379,15 +2379,19 @@ template void f1(T t) { constexpr int k = t.size(); } - template void f2(const T &t) { // expected-note 2{{declared here}} - constexpr int k = t.size(); // expected-error 2{{constant}} expected-note 2{{function parameter 't' with unknown value cannot be used in a constant expression}} + template void f2a(const T &t) { + constexpr int k1 = t.size(); + constexpr int k2 = (t).size(); + } + template void f2b(const T &t) { // expected-note {{declared here}} + constexpr int k = t.size(); // expected-error {{constant}} expected-note {{function parameter 't' with unknown value cannot be used in a constant expression}} } template void f3(const T &t) { constexpr int k = T::size(); } void g(array<3> a) { f1(a); - f2(a); // expected-note {{instantiation of}} + f2a(a); f3(a); } @@ -2396,7 +2400,7 @@ }; void h(array_nonstatic<3> a) { f1(a); - f2(a); // expected-note {{instantiation of}} + f2b(a); // expected-note {{instantiation of}} } }