CertC++-DCL52

Never qualify a reference type with const or volatile

Required inputs: IR

C++ does not allow you to change the value of a reference type, effectively treating all references as being const qualified. The C++ Standard, [dcl.ref], paragraph 1 [ ISO/IEC 14882-2014], states the following:

Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name (7.1.3, 14.1) or decltype-specifier (7.1.6.2), in which case the cv-qualifiers are ignored.

Thus, C++ prohibits or ignores the cv-qualification of a reference type. Only a value of non-reference type may be cv-qualified.

When attempting to const-qualify a type as part of a declaration that uses reference type, a programmer may accidentally write

char &const p;

instead of

char const &p; // Or: const char &p;

Do not attempt to cv-qualify a reference type because it results in undefined behavior. A conforming compiler is required to issue a diagnostic message. However, if the compiler does not emit a  fatal diagnostic, the program may produce surprising results, such as allowing the character referenced by  p to be mutated.

Noncompliant Code Example

In this noncompliant code example, a const-qualified reference to a char is formed instead of a reference to a const-qualified char. This results in undefined behavior.

#include <iostream>
 
void f(char c) {
  char &const p = c;
  p = 'p';
  std::cout << c << std::endl;
}
Implementation Details (MSVC)

With Microsoft Visual Studio 2015, this code compiles successfully with a warning diagnostic.

warning C4227: anachronism used : qualifiers on reference are ignored

When run, the code outputs the following.

p
Implementation Details (Clang)

With Clang3.9, this code produces a fatal diagnostic.

error: 'const' qualifier may not be applied to a reference
Noncompliant Code Example

This noncompliant code example correctly declares p to be a reference to a const-qualified  char. The subsequent modification of  p makes the program ill-formed.

#include <iostream>
 
void f(char c) {
  const char &p = c;
  p = 'p'; // Error: read-only variable is not assignable
  std::cout << c << std::endl;
}
Compliant Solution

This compliant solution removes the const qualifier.

#include <iostream>

void f(char c) {
  char &p = c;
  p = 'p';
  std::cout << c << std::endl;
}
Risk Assessment

A const or volatile reference type may result in undefined behavior instead of a fatal diagnostic, causing unexpected values to be stored and leading to possible data integrity violations.

Rule Severity Likelihood Remediation Cost Priority Level
DCL52-CPP Low Unlikely Low P3 L3
Bibliography
[ Dewhurst 2002] Gotcha #5, "Misunderstanding References"
[ ISO/IEC 14882-2014] Subclause 8.3.2, "References"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/declarations-and-initialization-dcl/dcl52-cpp], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

cafe_message

{}

None

False

Options

message_predicate

message_predicate : typing.Callable[[Cafe_Message], bool] | None = None

If provided, a custom predicate to filter relevant messages. Receives the message node and should return True for messages to report.
 

reported_messages

reported_messages : set[int] | None = {512}

If provided, only messages of these types are reported.
 

reported_severities

reported_severities : set[str] = {'error', 'remark', 'warning'}

List of severities to display.
 

use_error_number

use_error_number : bool = False

Whether the error number from the frontend should be used.
 

use_rule_severity

use_rule_severity : bool = True

Whether the rule's severity or the compiler's severity should be used.