summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td17
-rw-r--r--lib/Sema/SemaDeclCXX.cpp7
-rw-r--r--lib/Sema/SemaExpr.cpp21
-rw-r--r--lib/Sema/SemaType.cpp22
-rw-r--r--test/SemaCXX/deprecated.cpp69
-rwxr-xr-xwww/cxx_status.html2
7 files changed, 138 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 48874f98e5..396f297881 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -140,6 +140,7 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">;
+def DeprecatedVolatile : DiagGroup<"deprecated-volatile">;
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
[CXX11CompatDeprecatedWritableStr]>;
// FIXME: Why is DeprecatedImplementations not in this group?
@@ -150,6 +151,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
DeprecatedIncrementBool,
DeprecatedRegister,
DeprecatedThisCapture,
+ DeprecatedVolatile,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d0d1a7d4ea..9d1475d201 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6650,6 +6650,23 @@ def ext_increment_bool : ExtWarn<
DefaultError, InGroup<IncrementBool>;
def err_increment_decrement_enum : Error<
"cannot %select{decrement|increment}0 expression of enum type %1">;
+
+def warn_deprecated_increment_decrement_volatile : Warning<
+ "%select{decrement|increment}0 of object of volatile-qualified type %1 "
+ "is deprecated">, InGroup<DeprecatedVolatile>;
+def warn_deprecated_compound_assign_volatile : Warning<
+ "compound assignment to object of volatile-qualified type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_return : Warning<
+ "volatile-qualified return type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_param : Warning<
+ "volatile-qualified parameter type %0 is deprecated">,
+ InGroup<DeprecatedVolatile>;
+def warn_deprecated_volatile_structured_binding : Warning<
+ "volatile qualifier in structured binding declaration is deprecated">,
+ InGroup<DeprecatedVolatile>;
+
def err_catch_incomplete_ptr : Error<
"cannot catch pointer to incomplete type %0">;
def err_catch_incomplete_ref : Error<
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9863398159..ff90b9548e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -775,6 +775,13 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
return nullptr;
}
+ // C++2a [dcl.struct.bind]p1:
+ // A cv that includes volatile is deprecated
+ if ((DS.getTypeQualifiers() & DeclSpec::TQ_volatile) &&
+ getLangOpts().CPlusPlus2a)
+ Diag(DS.getVolatileSpecLoc(),
+ diag::warn_deprecated_volatile_structured_binding);
+
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index d158eaabde..b691668da8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11938,6 +11938,21 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
CheckForNullPointerDereference(*this, LHSExpr);
+ if (getLangOpts().CPlusPlus2a && LHSType.isVolatileQualified()) {
+ if (CompoundType.isNull()) {
+ // C++2a [expr.ass]p5:
+ // A simple-assignment whose left operand is of a volatile-qualified
+ // type is deprecated unless the assignment is either a discarded-value
+ // expression or an unevaluated operand
+ // FIXME: Implement checks for this.
+ } else {
+ // C++2a [expr.ass]p6:
+ // [Compound-assignment] expressions are deprecated if E1 has
+ // volatile-qualified type
+ Diag(Loc, diag::warn_deprecated_compound_assign_volatile) << LHSType;
+ }
+ }
+
// C99 6.5.16p3: The type of an assignment expression is the type of the
// left operand unless the left operand has qualified type, in which case
// it is the unqualified version of the type of the left operand.
@@ -12126,6 +12141,12 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// Now make sure the operand is a modifiable lvalue.
if (CheckForModifiableLvalue(Op, OpLoc, S))
return QualType();
+ if (S.getLangOpts().CPlusPlus2a && ResType.isVolatileQualified()) {
+ // C++2a [expr.pre.inc]p1, [expr.post.inc]p1:
+ // An operand with volatile-qualified type is deprecated
+ S.Diag(OpLoc, diag::warn_deprecated_increment_decrement_volatile)
+ << IsInc << ResType;
+ }
// In C++, a prefix increment is the same type as the operand. Otherwise
// (in C or with postfix), the increment is the unqualified type of the
// operand.
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 87a672c537..fccdb2bc2e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2475,6 +2475,11 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn,
NTCUK_Destruct|NTCUK_Copy);
+ // C++2a [dcl.fct]p12:
+ // A volatile-qualified return type is deprecated
+ if (T.isVolatileQualified() && getLangOpts().CPlusPlus2a)
+ Diag(Loc, diag::warn_deprecated_volatile_return) << T;
+
return false;
}
@@ -2555,6 +2560,11 @@ QualType Sema::BuildFunctionType(QualType T,
Invalid = true;
}
+ // C++2a [dcl.fct]p4:
+ // A parameter with volatile-qualified type is deprecated
+ if (ParamType.isVolatileQualified() && getLangOpts().CPlusPlus2a)
+ Diag(Loc, diag::warn_deprecated_volatile_param) << ParamType;
+
ParamTypes[Idx] = ParamType;
}
@@ -4685,6 +4695,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T;
} else
diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
+
+ // C++2a [dcl.fct]p12:
+ // A volatile-qualified return type is deprecated
+ if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus2a)
+ S.Diag(DeclType.Loc, diag::warn_deprecated_volatile_return) << T;
}
// Objective-C ARC ownership qualifiers are ignored on the function
@@ -5168,6 +5183,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
T->isObjectType())
T.addConst();
+ // C++2a [dcl.fct]p4:
+ // A parameter with volatile-qualified type is deprecated
+ if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus2a &&
+ (D.getContext() == DeclaratorContext::PrototypeContext ||
+ D.getContext() == DeclaratorContext::LambdaExprParameterContext))
+ S.Diag(D.getIdentifierLoc(), diag::warn_deprecated_volatile_param) << T;
+
// If there was an ellipsis in the declarator, the declaration declares a
// parameter pack whose type may be a pack expansion type.
if (D.hasEllipsis()) {
diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp
index b5760c37cf..36c73b0a27 100644
--- a/test/SemaCXX/deprecated.cpp
+++ b/test/SemaCXX/deprecated.cpp
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -std=c++11 %s -Wdeprecated -verify -triple x86_64-linux-gnu
// RUN: %clang_cc1 -std=c++14 %s -Wdeprecated -verify -triple x86_64-linux-gnu
// RUN: %clang_cc1 -std=c++17 %s -Wdeprecated -verify -triple x86_64-linux-gnu
-// RUN: %clang_cc1 -std=c++2a %s -Wdeprecated -verify -triple x86_64-linux-gnu
+// RUN: %clang_cc1 -std=c++2a %s -Wdeprecated -verify=expected,cxx20 -triple x86_64-linux-gnu
// RUN: %clang_cc1 -std=c++14 %s -Wdeprecated -verify -triple x86_64-linux-gnu -Wno-deprecated-register -DNO_DEPRECATED_FLAGS
@@ -125,5 +125,72 @@ void array_index_comma() {
X()[(X(), X())];
}
+namespace DeprecatedVolatile {
+ volatile int n = 1;
+ void use(int);
+ void f() {
+ // simple assignments are deprecated only if their value is used
+ n = 5; // ok
+#if __cplusplus >= 201103L
+ decltype(n = 5) m = n; // ok expected-warning {{side effects}}
+ m = sizeof(n = 5); // ok expected-warning {{side effects}}
+#endif
+ (n = 5, 0); // ok
+ use(n = 5); // FIXME: deprecated
+ (n = 5); // FIXME: deprecated
+ int q = n = 5; // FIXME: deprecated
+ q = n = 5; // FIXME: deprecated
+#if __cplusplus >= 201103L
+ decltype(q = n = 5) m2 = q; // FIXME: deprecated expected-warning {{side effects}}
+#endif
+ q = sizeof(q = n = 5); // FIXME: deprecated expected-warning {{side effects}}
+
+ // inc / dec / compound assignments are always deprecated
+ ++n; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
+ --n; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
+ n++; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
+ n--; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
+ n += 5; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
+ n *= 3; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
+ n /= 2; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
+ n %= 42; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
+
+#if __cplusplus >= 201703L
+ struct X { int a, b; };
+ volatile auto [x, y] = X{1, 2}; // cxx20-warning {{volatile qualifier in structured binding declaration is deprecated}}
+
+ struct Y { volatile int a, b; };
+ auto [x2, y2] = Y{1, 2}; // ok
+#endif
+ }
+ volatile int g( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
+ volatile int n, // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
+ volatile int (*p)( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
+ volatile int m) // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
+ );
+#if __cplusplus >= 201103L
+ auto lambda = []( // cxx20-warning{{volatile-qualified return type 'volatile int' is deprecated}}
+ volatile int n) // cxx20-warning{{volatile-qualified parameter type 'volatile int' is deprecated}}
+ -> volatile int { return n; };
+#endif
+
+ template<typename T> T f(T v); // cxx20-warning 2{{deprecated}}
+ int use_f = f<volatile int>(0); // FIXME: Missing "in instantiation of" note.
+
+ // OK, only the built-in operators are deprecated.
+ struct UDT {
+ UDT(volatile const UDT&);
+ UDT &operator=(const UDT&);
+ UDT &operator=(const UDT&) volatile;
+ UDT operator+=(const UDT&) volatile;
+ };
+ void h(UDT a) {
+ volatile UDT b = a;
+ volatile UDT c = b;
+ a = c = a;
+ b += a;
+ }
+}
+
# 1 "/usr/include/system-header.h" 1 3
void system_header_function(void) throw();
diff --git a/www/cxx_status.html b/www/cxx_status.html
index e53dbc5206..0c6f3dec04 100755
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -1103,7 +1103,7 @@ as the draft C++2a standard evolves.
<tr>
<td>Deprecate some problematic uses of <tt>volatile</tt></td>
<td><a href="http://wg21.link/p1152r4">P1152R4</a></td>
- <td class="none" align="center">No</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr>
<td><tt>[[nodiscard("with reason")]]</tt></td>