diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp
index 48736f805ebd389fb838c7c901a02e3dbce411a4..05a7a083d384e8730e3d336665ef5f139eb2fdab 100644
--- a/src/libs/cplusplus/pp-engine.cpp
+++ b/src/libs/cplusplus/pp-engine.cpp
@@ -906,7 +906,49 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
 {
     ScopedBoolSwap s(m_state.m_inPreprocessorDirective, true);
 
-    Macro *macro = m_env->resolve(tk->asByteArrayRef());
+    static const QByteArray ppLine("__LINE__");
+    static const QByteArray ppFile("__FILE__");
+    static const QByteArray ppDate("__DATE__");
+    static const QByteArray ppTime("__TIME__");
+
+    ByteArrayRef macroNameRef = tk->asByteArrayRef();
+
+    if (macroNameRef.size() == 8
+            && macroNameRef[0] == '_'
+            && macroNameRef[1] == '_') {
+        PPToken newTk;
+        if (macroNameRef == ppLine) {
+            QByteArray txt = QByteArray::number(tk->lineno);
+            newTk = generateToken(T_STRING_LITERAL, txt.constData(), txt.size(), tk->lineno, false);
+        } else if (macroNameRef == ppFile) {
+            QByteArray txt;
+            txt.append('"');
+            txt.append(m_env->currentFileUtf8);
+            txt.append('"');
+            newTk = generateToken(T_STRING_LITERAL, txt.constData(), txt.size(), tk->lineno, false);
+        } else if (macroNameRef == ppDate) {
+            QByteArray txt;
+            txt.append('"');
+            txt.append(QDate::currentDate().toString().toUtf8());
+            txt.append('"');
+            newTk = generateToken(T_STRING_LITERAL, txt.constData(), txt.size(), tk->lineno, false);
+        } else if (macroNameRef == ppTime) {
+            QByteArray txt;
+            txt.append('"');
+            txt.append(QTime::currentTime().toString().toUtf8());
+            txt.append('"');
+            newTk = generateToken(T_STRING_LITERAL, txt.constData(), txt.size(), tk->lineno, false);
+        }
+
+        if (newTk.hasSource()) {
+            newTk.f.newline = tk->newline();
+            newTk.f.whitespace = tk->whitespace();
+            *tk = newTk;
+            return false;
+        }
+    }
+
+    Macro *macro = m_env->resolve(macroNameRef);
     if (!macro
             || (tk->expanded()
                 && m_state.m_tokenBuffer
diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp
index 7d3f44c06b6809d9202a750d78c580b0c60f7373..2594bc692f6f796483c106f4bada75c46e34eb75 100644
--- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp
+++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp
@@ -334,6 +334,7 @@ private slots:
     void unfinished_function_like_macro_call();
     void nasty_macro_expansion();
     void glib_attribute();
+    void builtin__FILE__();
     void blockSkipping();
     void includes_1();
     void dont_eagerly_expand();
@@ -783,6 +784,23 @@ void tst_Preprocessor::glib_attribute()
     QCOMPARE(preprocessed, result____);
 }
 
+void tst_Preprocessor::builtin__FILE__()
+{
+    Client *client = 0; // no client.
+    Environment env;
+
+    Preprocessor preprocess(client, &env);
+    QByteArray preprocessed = preprocess.run(
+                QLatin1String("some-file.c"),
+                QByteArray("const char *f = __FILE__\n"
+                           ));
+    const QByteArray result____ =
+            "# 1 \"some-file.c\"\n"
+            "const char *f = \"some-file.c\"\n";
+
+    QCOMPARE(preprocessed, result____);
+}
+
 void tst_Preprocessor::comparisons_data()
 {
     QTest::addColumn<QString>("infile");